From da631ec01f3bfae8c1714ac8a6cb521932656362 Mon Sep 17 00:00:00 2001 From: Chip Reed Date: Wed, 6 Dec 2023 09:13:27 +0100 Subject: [PATCH 01/69] tauri-plugin concept --- Cargo.toml | 4 + core/tauri-plugin/Cargo.toml | 24 + core/tauri-plugin/src/build.rs | 55 + core/tauri-plugin/src/lib.rs | 25 + core/tauri-plugin/src/runtime.rs | 1 + .../plugins/tauri-plugin-example/.gitignore | 1 + .../plugins/tauri-plugin-example/Cargo.lock | 3564 +++++++++++++++++ .../plugins/tauri-plugin-example/Cargo.toml | 11 + .../plugins/tauri-plugin-example/build.rs | 3 + .../permissions/home-config.toml | 6 + .../permissions/home-dir.toml | 7 + .../tauri-plugin-example/permissions/set.toml | 17 + .../plugins/tauri-plugin-example/src/lib.rs | 14 + 13 files changed, 3732 insertions(+) create mode 100644 core/tauri-plugin/Cargo.toml create mode 100644 core/tauri-plugin/src/build.rs create mode 100644 core/tauri-plugin/src/lib.rs create mode 100644 core/tauri-plugin/src/runtime.rs create mode 100644 examples/plugins/tauri-plugin-example/.gitignore create mode 100644 examples/plugins/tauri-plugin-example/Cargo.lock create mode 100644 examples/plugins/tauri-plugin-example/Cargo.toml create mode 100644 examples/plugins/tauri-plugin-example/build.rs create mode 100644 examples/plugins/tauri-plugin-example/permissions/home-config.toml create mode 100644 examples/plugins/tauri-plugin-example/permissions/home-dir.toml create mode 100644 examples/plugins/tauri-plugin-example/permissions/set.toml create mode 100644 examples/plugins/tauri-plugin-example/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 6c6f337be6b4..00bce404c9b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,9 +10,13 @@ members = [ "core/tauri-build", "core/tauri-codegen", "core/tauri-config-schema", + "core/tauri-plugin", # integration tests "core/tests/restart", + + # examples that should be tested by default + "examples/plugins/*" ] exclude = [ diff --git a/core/tauri-plugin/Cargo.toml b/core/tauri-plugin/Cargo.toml new file mode 100644 index 000000000000..4203dc0d12b2 --- /dev/null +++ b/core/tauri-plugin/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "tauri-plugin" +version = "0.1.0" +authors = { workspace = true } +homepage = { workspace = true } +repository = { workspace = true } +categories = { workspace = true } +license = { workspace = true } +edition = { workspace = true } +rust-version = { workspace = true } + +[features] +build = ["dep:anyhow", "dep:cargo_metadata"] +runtime = ["dep:tauri"] + +[dependencies] +anyhow = { version = "1", optional = true } +cargo_metadata = { version = "0.18", optional = true } +tauri = { version = "2.0.0-alpha.18", default-features = false, path = "../tauri", optional = true } + +[package.metadata.docs.rs] +features = ["build", "runtime"] +rustc-args = [ "--cfg", "docsrs" ] +rustdoc-args = [ "--cfg", "docsrs" ] diff --git a/core/tauri-plugin/src/build.rs b/core/tauri-plugin/src/build.rs new file mode 100644 index 000000000000..2071af0c59cd --- /dev/null +++ b/core/tauri-plugin/src/build.rs @@ -0,0 +1,55 @@ +use anyhow::{bail, ensure, Context, Result}; +use cargo_metadata::{Metadata, MetadataCommand}; + +/// [`try_build`] but will exit automatically if an error is found. +pub fn build() { + if let Err(error) = try_build() { + println!("{}: {}", env!("CARGO_PKG_NAME"), error); + std::process::exit(1); + } +} + +/// Ensure this crate is properly configured to be a Tauri plugin. +/// +/// # Errors +/// +/// Errors will occur if environmental variables expected to be set inside of [build scripts] +/// are not found, or if the crate violates Tauri plugin conventions. +pub fn try_build() -> Result<()> { + // convention: plugin names should not use underscores + let name = build_var("CARGO_PKG_NAME")?; + ensure!( + !name.contains('_'), + "names of Tauri plugins should not use underscores, only hyphens" + ); + + // requirement: links MUST be set and MUST match the name + match build_var("CARGO_MANIFEST_LINKS") { + Ok(links) => ensure!(name == links, "package.links field in the Cargo manifest MUST be set to the same value as package.name"), + Err(_) => bail!("package.links field in the Cargo manifest is not set, it should be set to the same as package.name") + } + + let metadata = find_metadata()?; + println!("{metadata:#?}"); + + Ok(()) +} + +/// Grab an env var that is expected to be set inside of build scripts. +fn build_var(key: &str) -> Result { + std::env::var(key).with_context(|| format!("expected build script env var {key}, but it was not found - ensure this is called in a build script")) +} + +fn find_metadata() -> Result { + build_var("CARGO_MANIFEST_DIR") + .and_then(|p| { + std::fs::canonicalize(p).context("CARGO_MANIFEST_DIR was not able to be canonicalized") + }) + .and_then(|dir| { + MetadataCommand::new() + .current_dir(dir) + .no_deps() + .exec() + .context("failed to grab Cargo manifest") + }) +} diff --git a/core/tauri-plugin/src/lib.rs b/core/tauri-plugin/src/lib.rs new file mode 100644 index 000000000000..c32c3e683fd8 --- /dev/null +++ b/core/tauri-plugin/src/lib.rs @@ -0,0 +1,25 @@ +// Copyright 2019-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + +//! [![](https://github.com/tauri-apps/tauri/raw/dev/.github/splash.png)](https://tauri.app) +//! +//! Interface for building Tauri plugins. + +#![doc( + html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png", + html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png" +)] +#![cfg_attr(docsrs, feature(doc_cfg))] + +#[cfg(feature = "build")] +mod build; +#[cfg(feature = "runtime")] +mod runtime; + +#[cfg(feature = "build")] +#[cfg_attr(docsrs, doc(feature = "build"))] +pub use build::*; +#[cfg(feature = "runtime")] +#[cfg_attr(docsrs, doc(feature = "runtime"))] +pub use runtime::*; diff --git a/core/tauri-plugin/src/runtime.rs b/core/tauri-plugin/src/runtime.rs new file mode 100644 index 000000000000..8b137891791f --- /dev/null +++ b/core/tauri-plugin/src/runtime.rs @@ -0,0 +1 @@ + diff --git a/examples/plugins/tauri-plugin-example/.gitignore b/examples/plugins/tauri-plugin-example/.gitignore new file mode 100644 index 000000000000..ea8c4bf7f35f --- /dev/null +++ b/examples/plugins/tauri-plugin-example/.gitignore @@ -0,0 +1 @@ +/target diff --git a/examples/plugins/tauri-plugin-example/Cargo.lock b/examples/plugins/tauri-plugin-example/Cargo.lock new file mode 100644 index 000000000000..c1b6388ec607 --- /dev/null +++ b/examples/plugins/tauri-plugin-example/Cargo.lock @@ -0,0 +1,3564 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + +[[package]] +name = "atk" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4af014b17dd80e8af9fa689b2d4a211ddba6eb583c1622f35d0cb543f6b17e4" +dependencies = [ + "atk-sys", + "glib", + "libc", +] + +[[package]] +name = "atk-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "251e0b7d90e33e0ba930891a505a9a35ece37b2dd37a14f3ffc306c13b980009" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.21.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +dependencies = [ + "serde", +] + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +dependencies = [ + "serde", +] + +[[package]] +name = "cairo-rs" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f33613627f0dea6a731b0605101fad59ba4f193a52c96c4687728d822605a8a1" +dependencies = [ + "bitflags 2.4.1", + "cairo-sys-rs", + "glib", + "libc", + "once_cell", + "thiserror", +] + +[[package]] +name = "cairo-sys-rs" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "camino" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e34637b3140142bdf929fb439e8aa4ebad7651ebf7b1080b3930aa16ac1459ff" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cargo_toml" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d1ece59890e746567b467253aea0adbe8a21784d0b025d8a306f66c391c2957" +dependencies = [ + "serde", + "toml 0.8.8", +] + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cfb" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f" +dependencies = [ + "byteorder", + "fnv", + "uuid", +] + +[[package]] +name = "cfg-expr" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03915af431787e6ffdcc74c645077518c6b6e01f80b761e0fbbfa288536311b3" +dependencies = [ + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets 0.48.5", +] + +[[package]] +name = "cocoa" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" +dependencies = [ + "bitflags 1.3.2", + "block", + "cocoa-foundation", + "core-foundation", + "core-graphics", + "foreign-types", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" +dependencies = [ + "bitflags 1.3.2", + "block", + "core-foundation", + "core-graphics-types", + "libc", + "objc", +] + +[[package]] +name = "combine" +version = "4.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "core-graphics" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "970a29baf4110c26fedbc7f82107d42c23f7e88e404c4577ed73fe99ff85a212" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "cssparser" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa 0.4.8", + "matches", + "phf 0.8.0", + "proc-macro2", + "quote", + "smallvec", + "syn 1.0.109", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn 2.0.39", +] + +[[package]] +name = "ctor" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37e366bff8cd32dd8754b0991fb66b279dc48f598c3a18914852a6673deef583" +dependencies = [ + "quote", + "syn 2.0.39", +] + +[[package]] +name = "darling" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.39", +] + +[[package]] +name = "darling_macro" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "deranged" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "dtoa-short" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbaceec3c6e4211c79e7b1800fb9680527106beb2f9c51904a3210c03a448c74" +dependencies = [ + "dtoa", +] + +[[package]] +name = "dunce" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" + +[[package]] +name = "embed-resource" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f54cc3e827ee1c3812239a9a41dede7b4d7d5d5464faa32d71bd7cba28ce2cb2" +dependencies = [ + "cc", + "rustc_version", + "toml 0.8.8", + "vswhom", + "winreg 0.51.0", +] + +[[package]] +name = "embed_plist" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" + +[[package]] +name = "encoding_rs" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fdeflate" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64d6dafc854908ff5da46ff3f8f473c6984119a2876a383a860246dd7841a868" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "field-offset" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" +dependencies = [ + "memoffset", + "rustc_version", +] + +[[package]] +name = "flate2" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + +[[package]] +name = "futures-channel" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" + +[[package]] +name = "futures-executor" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" + +[[package]] +name = "futures-macro" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "futures-sink" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" + +[[package]] +name = "futures-task" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" + +[[package]] +name = "futures-util" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +dependencies = [ + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "gdk" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5ba081bdef3b75ebcdbfc953699ed2d7417d6bd853347a42a37d76406a33646" +dependencies = [ + "cairo-rs", + "gdk-pixbuf", + "gdk-sys", + "gio", + "glib", + "libc", + "pango", +] + +[[package]] +name = "gdk-pixbuf" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "446f32b74d22c33b7b258d4af4ffde53c2bf96ca2e29abdf1a785fe59bd6c82c" +dependencies = [ + "gdk-pixbuf-sys", + "gio", + "glib", + "libc", + "once_cell", +] + +[[package]] +name = "gdk-pixbuf-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gdk-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31ff856cb3386dae1703a920f803abafcc580e9b5f711ca62ed1620c25b51ff2" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "pkg-config", + "system-deps", +] + +[[package]] +name = "generator" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "windows 0.48.0", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "gio" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d809baf02bdf1b5ef4ad3bf60dd9d4977149db4612b7bbb58e56aef168193b" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "gio-sys", + "glib", + "libc", + "once_cell", + "pin-project-lite", + "smallvec", + "thiserror", +] + +[[package]] +name = "gio-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", + "winapi", +] + +[[package]] +name = "glib" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58cf801b6f7829fa76db37449ab67c9c98a2b1bf21076d9113225621e61a0fa6" +dependencies = [ + "bitflags 2.4.1", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "futures-util", + "gio-sys", + "glib-macros", + "glib-sys", + "gobject-sys", + "libc", + "memchr", + "once_cell", + "smallvec", + "thiserror", +] + +[[package]] +name = "glib-macros" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72793962ceece3863c2965d7f10c8786323b17c7adea75a515809fa20ab799a5" +dependencies = [ + "heck", + "proc-macro-crate 2.0.0", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "glib-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898" +dependencies = [ + "libc", + "system-deps", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "gobject-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gtk" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93c4f5e0e20b60e10631a5f06da7fe3dda744b05ad0ea71fee2f47adf865890c" +dependencies = [ + "atk", + "cairo-rs", + "field-offset", + "futures-channel", + "gdk", + "gdk-pixbuf", + "gio", + "glib", + "gtk-sys", + "gtk3-macros", + "libc", + "pango", + "pkg-config", +] + +[[package]] +name = "gtk-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771437bf1de2c1c0b496c11505bdf748e26066bbe942dfc8f614c9460f6d7722" +dependencies = [ + "atk-sys", + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "system-deps", +] + +[[package]] +name = "gtk3-macros" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6063efb63db582968fb7df72e1ae68aa6360dcfb0a75143f34fc7d616bad75e" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "h2" +version = "0.3.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 2.1.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "html5ever" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "http" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +dependencies = [ + "bytes", + "fnv", + "itoa 1.0.9", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa 1.0.9", + "pin-project-lite", + "socket2 0.4.10", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core 0.51.1", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ico" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3804960be0bb5e4edb1e1ad67afd321a9ecfd875c3e65c099468fd2717d7cae" +dependencies = [ + "byteorder", + "png", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", + "serde", +] + +[[package]] +name = "infer" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb33622da908807a06f9513c19b3c1ad50fab3e4137d82a78107d502075aa199" +dependencies = [ + "cfb", +] + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "javascriptcore-rs" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca5671e9ffce8ffba57afc24070e906da7fc4b1ba66f2cabebf61bf2ea257fcc" +dependencies = [ + "bitflags 1.3.2", + "glib", + "javascriptcore-rs-sys", +] + +[[package]] +name = "javascriptcore-rs-sys" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1be78d14ffa4b75b66df31840478fef72b51f8c2465d4ca7c194da9f7a5124" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "js-sys" +version = "0.3.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "json-patch" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ff1e1486799e3f64129f8ccad108b38290df9cd7015cd31bed17239f0789d6" +dependencies = [ + "serde", + "serde_json", + "thiserror", + "treediff", +] + +[[package]] +name = "keyboard-types" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" +dependencies = [ + "bitflags 2.4.1", + "serde", + "unicode-segmentation", +] + +[[package]] +name = "kuchikiki" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e4755b7b995046f510a7520c42b2fed58b77bd94d5a87a8eb43d2fd126da8" +dependencies = [ + "cssparser", + "html5ever", + "indexmap 1.9.3", + "matches", + "selectors", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" + +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.1", + "libc", + "redox_syscall", +] + +[[package]] +name = "line-wrap" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9" +dependencies = [ + "safemem", +] + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "loom" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "serde", + "serde_json", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "markup5ever" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" +dependencies = [ + "log", + "phf 0.10.1", + "phf_codegen 0.10.0", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "matches" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" + +[[package]] +name = "memchr" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +dependencies = [ + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.48.0", +] + +[[package]] +name = "muda" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b564d551449738387fb4541aef5fbfceaa81b2b732f2534c1c7c89dc7d673eaa" +dependencies = [ + "cocoa", + "crossbeam-channel", + "gtk", + "keyboard-types", + "objc", + "once_cell", + "png", + "serde", + "thiserror", + "windows-sys 0.52.0", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-traits" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "object" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "pango" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4" +dependencies = [ + "gio", + "glib", + "libc", + "once_cell", + "pango-sys", +] + +[[package]] +name = "pango-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.48.5", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "phf" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" +dependencies = [ + "phf_macros 0.8.0", + "phf_shared 0.8.0", + "proc-macro-hack", +] + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared 0.10.0", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros 0.11.2", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_codegen" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" +dependencies = [ + "phf_generator 0.8.0", + "phf_shared 0.8.0", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + +[[package]] +name = "phf_generator" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" +dependencies = [ + "phf_shared 0.8.0", + "rand 0.7.3", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand 0.8.5", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared 0.11.2", + "rand 0.8.5", +] + +[[package]] +name = "phf_macros" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c" +dependencies = [ + "phf_generator 0.8.0", + "phf_shared 0.8.0", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "phf_shared" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" + +[[package]] +name = "plist" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef" +dependencies = [ + "base64", + "indexmap 2.1.0", + "line-wrap", + "quick-xml", + "serde", + "time", +] + +[[package]] +name = "png" +version = "0.17.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" +dependencies = [ + "toml_edit 0.20.7", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + +[[package]] +name = "proc-macro2" +version = "1.0.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quick-xml" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", + "rand_pcg", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.11", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "raw-window-handle" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +dependencies = [ + "getrandom 0.2.11", + "libredox", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.3", + "regex-syntax 0.8.2", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.2", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "reqwest" +version = "0.11.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "system-configuration", + "tokio", + "tokio-util", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "winreg 0.50.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "selectors" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe" +dependencies = [ + "bitflags 1.3.2", + "cssparser", + "derive_more", + "fxhash", + "log", + "matches", + "phf 0.8.0", + "phf_codegen 0.8.0", + "precomputed-hash", + "servo_arc", + "smallvec", + "thin-slice", +] + +[[package]] +name = "semver" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +dependencies = [ + "serde", +] + +[[package]] +name = "serde" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "serde_json" +version = "1.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +dependencies = [ + "itoa 1.0.9", + "ryu", + "serde", +] + +[[package]] +name = "serde_repr" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "serde_spanned" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa 1.0.9", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23" +dependencies = [ + "base64", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.1.0", + "serde", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "serialize-to-javascript" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9823f2d3b6a81d98228151fdeaf848206a7855a7a042bbf9bf870449a66cafb" +dependencies = [ + "serde", + "serde_json", + "serialize-to-javascript-impl", +] + +[[package]] +name = "serialize-to-javascript-impl" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74064874e9f6a15f04c1f3cb627902d0e6b410abbf36668afa873c61889f1763" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "servo_arc" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98238b800e0d1576d8b6e3de32827c2d74bee68bb97748dcf5071fb53965432" +dependencies = [ + "nodrop", + "stable_deref_trait", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" + +[[package]] +name = "socket2" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "socket2" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "soup3" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "471f924a40f31251afc77450e781cb26d55c0b650842efafc9c6cbd2f7cc4f9f" +dependencies = [ + "futures-channel", + "gio", + "glib", + "libc", + "soup3-sys", +] + +[[package]] +name = "soup3-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebe8950a680a12f24f15ebe1bf70db7af98ad242d9db43596ad3108aab86c27" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "state" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b8c4a4445d81357df8b1a650d0d0d6fbbbfe99d064aa5e02f3e4022061476d8" +dependencies = [ + "loom", +] + +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "swift-rs" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bbdb58577b6301f8d17ae2561f32002a5bae056d444e0f69e611e504a276204" +dependencies = [ + "base64", + "serde", + "serde_json", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "system-deps" +version = "6.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2d580ff6a20c55dfb86be5f9c238f67835d0e81cbdea8bf5680e0897320331" +dependencies = [ + "cfg-expr", + "heck", + "pkg-config", + "toml 0.8.8", + "version-compare", +] + +[[package]] +name = "target-lexicon" +version = "0.12.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" + +[[package]] +name = "tauri" +version = "2.0.0-alpha.18" +dependencies = [ + "anyhow", + "bytes", + "cocoa", + "dirs-next", + "embed_plist", + "futures-util", + "getrandom 0.2.11", + "glob", + "gtk", + "heck", + "http", + "jni", + "libc", + "log", + "mime", + "muda", + "objc", + "once_cell", + "percent-encoding", + "raw-window-handle", + "reqwest", + "serde", + "serde_json", + "serde_repr", + "serialize-to-javascript", + "state", + "swift-rs", + "tauri-build", + "tauri-macros", + "tauri-runtime", + "tauri-utils", + "thiserror", + "tokio", + "url", + "webkit2gtk", + "webview2-com", + "window-vibrancy", + "windows 0.52.0", +] + +[[package]] +name = "tauri-build" +version = "2.0.0-alpha.12" +dependencies = [ + "anyhow", + "cargo_toml", + "dirs-next", + "heck", + "json-patch", + "plist", + "semver", + "serde", + "serde_json", + "swift-rs", + "tauri-utils", + "tauri-winres", + "walkdir", +] + +[[package]] +name = "tauri-codegen" +version = "2.0.0-alpha.11" +dependencies = [ + "base64", + "ico", + "json-patch", + "plist", + "png", + "proc-macro2", + "quote", + "semver", + "serde", + "serde_json", + "sha2", + "tauri-utils", + "thiserror", + "time", + "url", + "uuid", + "walkdir", +] + +[[package]] +name = "tauri-macros" +version = "2.0.0-alpha.11" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.39", + "tauri-codegen", + "tauri-utils", +] + +[[package]] +name = "tauri-plugin" +version = "0.1.0" +dependencies = [ + "anyhow", + "cargo_metadata", + "tauri", +] + +[[package]] +name = "tauri-plugin-maybe" +version = "0.1.0" +dependencies = [ + "tauri-plugin", +] + +[[package]] +name = "tauri-runtime" +version = "1.0.0-alpha.5" +dependencies = [ + "gtk", + "http", + "jni", + "raw-window-handle", + "serde", + "serde_json", + "tauri-utils", + "thiserror", + "url", + "windows 0.52.0", +] + +[[package]] +name = "tauri-utils" +version = "2.0.0-alpha.11" +dependencies = [ + "ctor", + "dunce", + "glob", + "heck", + "html5ever", + "infer", + "json-patch", + "kuchikiki", + "log", + "memchr", + "phf 0.11.2", + "proc-macro2", + "quote", + "semver", + "serde", + "serde_json", + "serde_with", + "thiserror", + "url", + "walkdir", +] + +[[package]] +name = "tauri-winres" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5993dc129e544393574288923d1ec447c857f3f644187f4fbf7d9a875fbfc4fb" +dependencies = [ + "embed-resource", + "toml 0.7.8", +] + +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + +[[package]] +name = "thin-slice" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" + +[[package]] +name = "thiserror" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "thread_local" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +dependencies = [ + "deranged", + "itoa 1.0.9", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +dependencies = [ + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "pin-project-lite", + "socket2 0.5.5", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "toml" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.19.15", +] + +[[package]] +name = "toml" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.21.0", +] + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.1.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.20.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" +dependencies = [ + "indexmap 2.1.0", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +dependencies = [ + "indexmap 2.1.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "treediff" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52984d277bdf2a751072b5df30ec0377febdb02f7696d64c2d7d54630bac4303" +dependencies = [ + "serde_json", +] + +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "uuid" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +dependencies = [ + "getrandom 0.2.11", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "version-compare" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "vswhom" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be979b7f07507105799e854203b470ff7c78a1639e330a58f183b5fea574608b" +dependencies = [ + "libc", + "vswhom-sys", +] + +[[package]] +name = "vswhom-sys" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b17ae1f6c8a2b28506cd96d412eebf83b4a0ff2cbefeeb952f2f9dfa44ba18" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "walkdir" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.39", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" + +[[package]] +name = "wasm-streams" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "web-sys" +version = "0.3.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webkit2gtk" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76b1bc1e54c581da1e9f179d0b38512ba358fb1af2d634a1affe42e37172361a" +dependencies = [ + "bitflags 1.3.2", + "cairo-rs", + "gdk", + "gdk-sys", + "gio", + "gio-sys", + "glib", + "glib-sys", + "gobject-sys", + "gtk", + "gtk-sys", + "javascriptcore-rs", + "libc", + "once_cell", + "soup3", + "webkit2gtk-sys", +] + +[[package]] +name = "webkit2gtk-sys" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62daa38afc514d1f8f12b8693d30d5993ff77ced33ce30cd04deebc267a6d57c" +dependencies = [ + "bitflags 1.3.2", + "cairo-sys-rs", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "gtk-sys", + "javascriptcore-rs-sys", + "libc", + "pkg-config", + "soup3-sys", + "system-deps", +] + +[[package]] +name = "webview2-com" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0ae9c7e420783826cf769d2c06ac9ba462f450eca5893bb8c6c6529a4e5dd33" +dependencies = [ + "webview2-com-macros", + "webview2-com-sys", + "windows 0.52.0", + "windows-core 0.52.0", + "windows-implement", + "windows-interface", +] + +[[package]] +name = "webview2-com-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac1345798ecd8122468840bcdf1b95e5dc6d2206c5e4b0eafa078d061f59c9bc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "webview2-com-sys" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6ad85fceee6c42fa3d61239eba5a11401bf38407a849ed5ea1b407df08cca72" +dependencies = [ + "thiserror", + "windows 0.52.0", + "windows-core 0.52.0", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "window-vibrancy" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af6abc2b9c56bd95887825a1ce56cde49a2a97c07e28db465d541f5098a2656c" +dependencies = [ + "cocoa", + "objc", + "raw-window-handle", + "windows-sys 0.52.0", + "windows-version", +] + +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core 0.52.0", + "windows-implement", + "windows-interface", + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-implement" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12168c33176773b86799be25e2a2ba07c7aab9968b37541f1094dbd7a60c8946" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "windows-interface" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d8dc32e0095a7eeccebd0e3f09e9509365ecb3fc6ac4d6f5f14a3f6392942d1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + +[[package]] +name = "windows-version" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75aa004c988e080ad34aff5739c39d0312f4684699d6d71fc8a198d057b8b9b4" +dependencies = [ + "windows-targets 0.52.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "winnow" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "winreg" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "937f3df7948156640f46aacef17a70db0de5917bda9c92b0f751f3a955b588fc" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] diff --git a/examples/plugins/tauri-plugin-example/Cargo.toml b/examples/plugins/tauri-plugin-example/Cargo.toml new file mode 100644 index 000000000000..6735e069b36d --- /dev/null +++ b/examples/plugins/tauri-plugin-example/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "tauri-plugin-example" +version = "0.1.0" +edition = "2021" +links = "tauri-plugin-example" + +[build-dependencies] +tauri-plugin = {path = "../../../core/tauri-plugin", features = ["build"]} + +[dependencies] +tauri-plugin = {path = "../../../core/tauri-plugin", features = ["runtime"]} diff --git a/examples/plugins/tauri-plugin-example/build.rs b/examples/plugins/tauri-plugin-example/build.rs new file mode 100644 index 000000000000..d9603122d5b2 --- /dev/null +++ b/examples/plugins/tauri-plugin-example/build.rs @@ -0,0 +1,3 @@ +fn main() { + tauri_plugin::build() +} \ No newline at end of file diff --git a/examples/plugins/tauri-plugin-example/permissions/home-config.toml b/examples/plugins/tauri-plugin-example/permissions/home-config.toml new file mode 100644 index 000000000000..4fc4a7d1a974 --- /dev/null +++ b/examples/plugins/tauri-plugin-example/permissions/home-config.toml @@ -0,0 +1,6 @@ +version = 1 +identifier = "deny-home-dir-config" +description = "This denies read access to the complete $HOME folder." + +[[scope.deny]] +path = "$HOME/.config" diff --git a/examples/plugins/tauri-plugin-example/permissions/home-dir.toml b/examples/plugins/tauri-plugin-example/permissions/home-dir.toml new file mode 100644 index 000000000000..a3641f838dd2 --- /dev/null +++ b/examples/plugins/tauri-plugin-example/permissions/home-dir.toml @@ -0,0 +1,7 @@ +version = 1 +identifier = "allow-home-dir" +description = "This allows read access to the complete $HOME folder." +commands.allow = [ "readDirectory", "readFile" ] + +[[scope.allow]] +path = "$HOME/**" diff --git a/examples/plugins/tauri-plugin-example/permissions/set.toml b/examples/plugins/tauri-plugin-example/permissions/set.toml new file mode 100644 index 000000000000..20583af0eb97 --- /dev/null +++ b/examples/plugins/tauri-plugin-example/permissions/set.toml @@ -0,0 +1,17 @@ +description = "Default permissions granted" +permissions = ["allow-home-read-only"] + +[[set]] +identifier = "allow-full-homefolder-access" +description = "This allows read and write access to the complete $HOME folder." +permissions = [ + "allow-home-read-only", + "allow-home-write-only" +] + +[[set]] +identifier = "deny-homefolder-config-access" +description = "This denies access to the $HOME/.config folder." +permissions = [ + "deny-home-dir-config" +] \ No newline at end of file diff --git a/examples/plugins/tauri-plugin-example/src/lib.rs b/examples/plugins/tauri-plugin-example/src/lib.rs new file mode 100644 index 000000000000..7d12d9af8195 --- /dev/null +++ b/examples/plugins/tauri-plugin-example/src/lib.rs @@ -0,0 +1,14 @@ +pub fn add(left: usize, right: usize) -> usize { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +} From 57986ef4fcec550a524ba37975f9dbe461d9dec5 Mon Sep 17 00:00:00 2001 From: Chip Reed Date: Mon, 11 Dec 2023 20:05:15 +0900 Subject: [PATCH 02/69] wip --- core/tauri-plugin/Cargo.toml | 6 +- core/tauri-plugin/src/build.rs | 55 ----- core/tauri-plugin/src/build/mod.rs | 82 +++++++ core/tauri-utils/Cargo.toml | 4 +- core/tauri-utils/src/acl/identifier.rs | 222 ++++++++++++++++++ core/tauri-utils/src/acl/mod.rs | 61 +++++ core/tauri-utils/src/acl/plugin.rs | 1 + core/tauri-utils/src/acl/value.rs | 82 +++++++ core/tauri-utils/src/lib.rs | 1 + .../plugins/tauri-plugin-example/Cargo.toml | 2 +- .../plugins/tauri-plugin-example/build.rs | 4 +- .../tauri-plugin-example/permissions/set.toml | 3 +- .../plugins/tauri-plugin-example/src/lib.rs | 14 +- 13 files changed, 466 insertions(+), 71 deletions(-) delete mode 100644 core/tauri-plugin/src/build.rs create mode 100644 core/tauri-plugin/src/build/mod.rs create mode 100644 core/tauri-utils/src/acl/identifier.rs create mode 100644 core/tauri-utils/src/acl/mod.rs create mode 100644 core/tauri-utils/src/acl/plugin.rs create mode 100644 core/tauri-utils/src/acl/value.rs diff --git a/core/tauri-plugin/Cargo.toml b/core/tauri-plugin/Cargo.toml index 4203dc0d12b2..da6e314cebb4 100644 --- a/core/tauri-plugin/Cargo.toml +++ b/core/tauri-plugin/Cargo.toml @@ -10,13 +10,13 @@ edition = { workspace = true } rust-version = { workspace = true } [features] -build = ["dep:anyhow", "dep:cargo_metadata"] -runtime = ["dep:tauri"] +build = ["dep:anyhow", "dep:cargo_metadata", "dep:thiserror"] [dependencies] anyhow = { version = "1", optional = true } +thiserror = { version = "1", optional = true } cargo_metadata = { version = "0.18", optional = true } -tauri = { version = "2.0.0-alpha.18", default-features = false, path = "../tauri", optional = true } +tauri = { version = "2.0.0-alpha.18", default-features = false, path = "../tauri" } [package.metadata.docs.rs] features = ["build", "runtime"] diff --git a/core/tauri-plugin/src/build.rs b/core/tauri-plugin/src/build.rs deleted file mode 100644 index 2071af0c59cd..000000000000 --- a/core/tauri-plugin/src/build.rs +++ /dev/null @@ -1,55 +0,0 @@ -use anyhow::{bail, ensure, Context, Result}; -use cargo_metadata::{Metadata, MetadataCommand}; - -/// [`try_build`] but will exit automatically if an error is found. -pub fn build() { - if let Err(error) = try_build() { - println!("{}: {}", env!("CARGO_PKG_NAME"), error); - std::process::exit(1); - } -} - -/// Ensure this crate is properly configured to be a Tauri plugin. -/// -/// # Errors -/// -/// Errors will occur if environmental variables expected to be set inside of [build scripts] -/// are not found, or if the crate violates Tauri plugin conventions. -pub fn try_build() -> Result<()> { - // convention: plugin names should not use underscores - let name = build_var("CARGO_PKG_NAME")?; - ensure!( - !name.contains('_'), - "names of Tauri plugins should not use underscores, only hyphens" - ); - - // requirement: links MUST be set and MUST match the name - match build_var("CARGO_MANIFEST_LINKS") { - Ok(links) => ensure!(name == links, "package.links field in the Cargo manifest MUST be set to the same value as package.name"), - Err(_) => bail!("package.links field in the Cargo manifest is not set, it should be set to the same as package.name") - } - - let metadata = find_metadata()?; - println!("{metadata:#?}"); - - Ok(()) -} - -/// Grab an env var that is expected to be set inside of build scripts. -fn build_var(key: &str) -> Result { - std::env::var(key).with_context(|| format!("expected build script env var {key}, but it was not found - ensure this is called in a build script")) -} - -fn find_metadata() -> Result { - build_var("CARGO_MANIFEST_DIR") - .and_then(|p| { - std::fs::canonicalize(p).context("CARGO_MANIFEST_DIR was not able to be canonicalized") - }) - .and_then(|dir| { - MetadataCommand::new() - .current_dir(dir) - .no_deps() - .exec() - .context("failed to grab Cargo manifest") - }) -} diff --git a/core/tauri-plugin/src/build/mod.rs b/core/tauri-plugin/src/build/mod.rs new file mode 100644 index 000000000000..d8768cc58803 --- /dev/null +++ b/core/tauri-plugin/src/build/mod.rs @@ -0,0 +1,82 @@ +use cargo_metadata::{Metadata, MetadataCommand}; +use tauri::utils::acl::{Permission, PermissionSet}; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum Error { + #[error("expected build script env var {0}, but it was not found - ensure this is called in a build script")] + BuildVar(String), + + #[error("plugin names cannot contain underscores")] + CrateName, + + #[error("package.links field in the Cargo manifest is not set, it should be set to the same as package.name")] + LinksMissing, + + #[error( + "package.links field in the Cargo manifest MUST be set to the same value as package.name" + )] + LinksName, + + #[error("CARGO_MANIFEST_DIR could not canonicalize")] + Manifest(std::io::Error), + + #[error("failed to grab Cargo manifest: {0}")] + Metadata(#[from] cargo_metadata::Error), +} + +/// [`try_build`] but will exit automatically if an error is found. +pub fn build() { + if let Err(error) = try_build() { + println!("{}: {}", env!("CARGO_PKG_NAME"), error); + std::process::exit(1); + } +} + +/// Ensure this crate is properly configured to be a Tauri plugin. +/// +/// # Errors +/// +/// Errors will occur if environmental variables expected to be set inside of [build scripts] +/// are not found, or if the crate violates Tauri plugin conventions. +pub fn try_build() -> Result<(), Error> { + // convention: plugin names should not use underscores + let name = build_var("CARGO_PKG_NAME")?; + if name.contains('_') { + return Err(Error::CrateName); + } + + // requirement: links MUST be set and MUST match the name + let _links = build_var("CARGO_MANIFEST_LINKS")?; + + let metadata = find_metadata()?; + println!("{metadata:#?}"); + + Ok(()) +} + +/// Grab an env var that is expected to be set inside of build scripts. +fn build_var(key: &str) -> Result { + std::env::var(key).map_err(|_| Error::BuildVar(key.into())) +} + +fn find_metadata() -> Result { + build_var("CARGO_MANIFEST_DIR") + .and_then(|p| std::fs::canonicalize(p).map_err(Error::Manifest)) + .and_then(|dir| { + MetadataCommand::new() + .current_dir(dir) + .no_deps() + .exec() + .map_err(Error::Metadata) + }) +} + +#[derive(Debug)] +struct PluginPermissions { + default: Permission, + sets: Option>, + permissions: Option>, +} + +impl PluginPermissions {} diff --git a/core/tauri-utils/Cargo.toml b/core/tauri-utils/Cargo.toml index b9624529561f..ffa5f269cbb6 100644 --- a/core/tauri-utils/Cargo.toml +++ b/core/tauri-utils/Cargo.toml @@ -30,7 +30,7 @@ getrandom = { version = "0.2", optional = true, features = [ "std" ] } serialize-to-javascript = { version = "=0.1.1", optional = true } ctor = "0.2" json5 = { version = "0.4", optional = true } -toml = { version = "0.8", optional = true } +toml = { version = "0.8", default-features = true } json-patch = "1.2" glob = { version = "0.3", optional = true } walkdir = { version = "2", optional = true } @@ -50,5 +50,5 @@ schema = [ "schemars" ] isolation = [ "aes-gcm", "getrandom", "serialize-to-javascript" ] process-relaunch-dangerous-allow-symlink-macos = [ ] config-json5 = [ "json5" ] -config-toml = [ "toml" ] +config-toml = [] resources = [ "glob", "walkdir" ] diff --git a/core/tauri-utils/src/acl/identifier.rs b/core/tauri-utils/src/acl/identifier.rs new file mode 100644 index 000000000000..0e6a3fd992b3 --- /dev/null +++ b/core/tauri-utils/src/acl/identifier.rs @@ -0,0 +1,222 @@ +use std::num::NonZeroU8; +use thiserror::Error; + +const IDENTIFIER_SEPARATOR: u8 = b':'; +const PLUGIN_PREFIX: &str = "tauri-plugin-"; + +// https://doc.rust-lang.org/cargo/reference/manifest.html#the-name-field +const MAX_LEN_PREFIX: usize = 64 - PLUGIN_PREFIX.len(); +const MAX_LEN_BASE: usize = 64; +const MAX_LEN_IDENTIFIER: usize = MAX_LEN_PREFIX + 1 + MAX_LEN_BASE; + +#[derive(Debug)] +pub struct Identifier { + inner: String, + separator: Option, +} + +impl AsRef for Identifier { + #[inline(always)] + fn as_ref(&self) -> &str { + &self.inner + } +} + +impl Identifier { + #[inline(always)] + pub fn get(&self) -> &str { + self.as_ref() + } + + pub fn get_base(&self) -> &str { + match self.separator_index() { + None => self.get(), + Some(i) => &self.inner[i + 1..], + } + } + + pub fn get_prefix(&self) -> Option<&str> { + self.separator_index().map(|i| &self.inner[0..i]) + } + + pub fn set_prefix(&mut self) -> Result<(), ParseIdentifierError> { + todo!() + } + + pub fn into_inner(self) -> (String, Option) { + (self.inner, self.separator) + } + + fn separator_index(&self) -> Option { + self.separator.map(|i| i.get() as usize) + } +} + +#[derive(Debug)] +enum ValidByte { + Separator, + Byte(u8), +} + +impl ValidByte { + fn lower_alpha(byte: u8) -> Option { + byte.is_ascii_lowercase().then_some(Self::Byte(byte)) + } + + fn lower_alpha_hyphen(byte: u8) -> Option { + matches!(byte, b'a'..=b'z' | b'-').then_some(Self::Byte(byte)) + } + + fn next(&self, next: u8) -> Option { + match (self, next) { + (ValidByte::Byte(b'-'), IDENTIFIER_SEPARATOR) => None, + (ValidByte::Separator, b'-') => None, + + (_, IDENTIFIER_SEPARATOR) => Some(ValidByte::Separator), + (ValidByte::Separator, next) => ValidByte::lower_alpha(next), + (ValidByte::Byte(b'-'), next) => ValidByte::lower_alpha(next), + (ValidByte::Byte(_), next) => ValidByte::lower_alpha_hyphen(next), + } + } +} + +#[derive(Debug, Error)] +pub enum ParseIdentifierError { + #[error("identifiers cannot start with {}", PLUGIN_PREFIX)] + StartsWithTauriPlugin, + + #[error("identifiers cannot be empty")] + Empty, + + #[error("identifiers cannot be longer than {}, found {0}", MAX_LEN_IDENTIFIER)] + Humungous(usize), + + #[error("identifiers can only include lowercase ASCII, hyphens which are not leading or trailing, and a single colon if using a prefix")] + InvalidFormat, + + #[error( + "identifiers can only include a single separator '{}'", + IDENTIFIER_SEPARATOR + )] + MultipleSeparators, + + #[error("identifiers cannot have a trailing hyphen")] + TrailingHyphen, + + #[error("identifiers cannot have a prefix without a base")] + PrefixWithoutBase, +} + +impl TryFrom for Identifier { + type Error = ParseIdentifierError; + + fn try_from(value: String) -> Result { + if value.starts_with(PLUGIN_PREFIX) { + return Err(Self::Error::StartsWithTauriPlugin); + } + + if value.is_empty() { + return Err(Self::Error::Empty); + } + + let mut bytes = value.bytes(); + if bytes.len() > MAX_LEN_IDENTIFIER { + return Err(Self::Error::Humungous(bytes.len())); + } + + // grab the first byte only before parsing the rest + let mut prev = bytes + .next() + .and_then(ValidByte::lower_alpha) + .ok_or(Self::Error::InvalidFormat)?; + + let mut idx = 0; + let mut seperator = None; + for byte in bytes { + idx += 1; // we already consumed first item + match prev.next(byte) { + None => return Err(Self::Error::InvalidFormat), + Some(next @ ValidByte::Byte(_)) => prev = next, + Some(ValidByte::Separator) => { + if seperator.is_none() { + // safe to unwrap because idx starts at 1 and cannot go over MAX_IDENTIFIER_LEN + seperator = Some(idx.try_into().unwrap()); + prev = ValidByte::Separator + } else { + return Err(Self::Error::MultipleSeparators); + } + } + } + } + + match prev { + // empty base + ValidByte::Separator => return Err(Self::Error::TrailingHyphen), + + // trailing hyphen + ValidByte::Byte(b'-') => return Err(Self::Error::PrefixWithoutBase), + + _ => (), + } + + Ok(Self { + inner: value, + separator: seperator, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn ident(s: impl Into) -> Result { + Identifier::try_from(s.into()) + } + + #[test] + fn max_len_fits_in_u8() { + assert!(MAX_LEN_IDENTIFIER < u8::MAX as usize) + } + + #[test] + fn format() { + assert!(ident("prefix:base").is_ok()); + + // bad + assert!(ident("tauri-plugin-prefix:base").is_err()); + + assert!(ident("-prefix-:-base-").is_err()); + assert!(ident("-prefix:base").is_err()); + assert!(ident("prefix-:base").is_err()); + assert!(ident("prefix:-base").is_err()); + assert!(ident("prefix:base-").is_err()); + + assert!(ident("pre--fix:base--sep").is_err()); + assert!(ident("prefix:base--sep").is_err()); + assert!(ident("pre--fix:base").is_err()); + + assert!(ident("prefix::base").is_err()); + assert!(ident(":base").is_err()); + assert!(ident("prefix:").is_err()); + assert!(ident(":prefix:base:").is_err()); + assert!(ident("base:").is_err()); + + assert!(ident("").is_err()); + assert!(ident("💩").is_err()); + + assert!(ident("a".repeat(MAX_LEN_IDENTIFIER + 1)).is_err()); + } + + #[test] + fn base() { + assert_eq!(ident("prefix:base").unwrap().get_base(), "base"); + assert_eq!(ident("base").unwrap().get_base(), "base"); + } + + #[test] + fn prefix() { + assert_eq!(ident("prefix:base").unwrap().get_prefix(), Some("prefix")); + assert_eq!(ident("base").unwrap().get_prefix(), None); + } +} diff --git a/core/tauri-utils/src/acl/mod.rs b/core/tauri-utils/src/acl/mod.rs new file mode 100644 index 000000000000..f2bc29a7a402 --- /dev/null +++ b/core/tauri-utils/src/acl/mod.rs @@ -0,0 +1,61 @@ +use std::num::NonZeroU64; + +pub use self::{identifier::*, value::*}; + +mod identifier; +pub mod plugin; +mod value; + +/// Allowed and denied commands inside a permission. +/// +/// If two commands clash inside of `allow` and `deny`, it should be denied by default. +#[derive(Debug)] +pub struct Commands { + /// Allowed command. + pub allow: Vec, + + /// Denied command, which takes priority. + pub deny: Vec, +} + +#[derive(Debug)] +pub struct Scopes { + allow: Value, + deny: Value, +} + +#[derive(Debug)] +pub struct InlinedPermission { + /// The version of the permission. + version: Option, + + /// A unique identifier for the permission. + identifier: Option, + + /// Human-readable description of what the permission does. + description: Option, + + /// Allowed or denied commands when using this permission. + commands: Commands, + + /// Allowed or denied scoped when using this permission. + scopes: Scopes, +} + +/// A permission. +#[derive(Debug)] +pub struct Permission { + inner: InlinedPermission, +} + +#[derive(Debug)] +pub struct PermissionSet { + /// A unique identifier for the permission. + identifier: Identifier, + + /// Human-readable description of what the permission does. + description: String, + + /// All permissions this set contains. + permissions: Vec, +} diff --git a/core/tauri-utils/src/acl/plugin.rs b/core/tauri-utils/src/acl/plugin.rs new file mode 100644 index 000000000000..8b137891791f --- /dev/null +++ b/core/tauri-utils/src/acl/plugin.rs @@ -0,0 +1 @@ + diff --git a/core/tauri-utils/src/acl/value.rs b/core/tauri-utils/src/acl/value.rs new file mode 100644 index 000000000000..368c216a104f --- /dev/null +++ b/core/tauri-utils/src/acl/value.rs @@ -0,0 +1,82 @@ +use std::collections::BTreeMap; + +/// A valid ACL number. +#[derive(Debug)] +pub enum Number { + /// Represents an [`i64`]. + Int(i64), + + /// Represents a [`f64`]. + Float(f64), +} + +impl From for Number { + #[inline(always)] + fn from(value: i64) -> Self { + Self::Int(value) + } +} + +impl From for Number { + #[inline(always)] + fn from(value: f64) -> Self { + Self::Float(value) + } +} + +/// All supported ACL values. +#[derive(Debug)] +pub enum Value { + /// Represents a [`bool`]. + Bool(bool), + + /// Represents a valid ACL [`Number`]. + Number(Number), + + /// Represents a [`String`]. + String(String), + + /// Represents a list of other [`Value`]s. + List(Vec), + + /// Represents a map of [`String`] keys to [`Value`]s. + Map(BTreeMap), +} + +impl From for Value { + #[inline(always)] + fn from(value: bool) -> Self { + Self::Bool(value) + } +} + +impl> From for Value { + #[inline(always)] + fn from(value: T) -> Self { + Self::Number(value.into()) + } +} + +impl From for Value { + #[inline(always)] + fn from(value: String) -> Self { + Value::String(value) + } +} + +impl From for Value { + #[inline(always)] + fn from(value: toml::Value) -> Self { + use toml::Value as Toml; + + match value { + Toml::String(s) => s.into(), + Toml::Integer(i) => i.into(), + Toml::Float(f) => f.into(), + Toml::Boolean(b) => b.into(), + Toml::Datetime(d) => d.to_string().into(), + Toml::Array(a) => Value::List(a.into_iter().map(Value::from).collect()), + Toml::Table(t) => Value::Map(t.into_iter().map(|(k, v)| (k, v.into())).collect()), + } + } +} diff --git a/core/tauri-utils/src/lib.rs b/core/tauri-utils/src/lib.rs index d09c0f15978e..28416d9b5e78 100644 --- a/core/tauri-utils/src/lib.rs +++ b/core/tauri-utils/src/lib.rs @@ -24,6 +24,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; use log::warn; +pub mod acl; pub mod assets; pub mod config; pub mod html; diff --git a/examples/plugins/tauri-plugin-example/Cargo.toml b/examples/plugins/tauri-plugin-example/Cargo.toml index 6735e069b36d..6181b3d0f237 100644 --- a/examples/plugins/tauri-plugin-example/Cargo.toml +++ b/examples/plugins/tauri-plugin-example/Cargo.toml @@ -8,4 +8,4 @@ links = "tauri-plugin-example" tauri-plugin = {path = "../../../core/tauri-plugin", features = ["build"]} [dependencies] -tauri-plugin = {path = "../../../core/tauri-plugin", features = ["runtime"]} +tauri-plugin = { path = "../../../core/tauri-plugin" } diff --git a/examples/plugins/tauri-plugin-example/build.rs b/examples/plugins/tauri-plugin-example/build.rs index d9603122d5b2..4ffc371441c7 100644 --- a/examples/plugins/tauri-plugin-example/build.rs +++ b/examples/plugins/tauri-plugin-example/build.rs @@ -1,3 +1,3 @@ fn main() { - tauri_plugin::build() -} \ No newline at end of file + tauri_plugin::build() +} diff --git a/examples/plugins/tauri-plugin-example/permissions/set.toml b/examples/plugins/tauri-plugin-example/permissions/set.toml index 20583af0eb97..75877ad0f421 100644 --- a/examples/plugins/tauri-plugin-example/permissions/set.toml +++ b/examples/plugins/tauri-plugin-example/permissions/set.toml @@ -1,3 +1,4 @@ +[default] description = "Default permissions granted" permissions = ["allow-home-read-only"] @@ -14,4 +15,4 @@ identifier = "deny-homefolder-config-access" description = "This denies access to the $HOME/.config folder." permissions = [ "deny-home-dir-config" -] \ No newline at end of file +] diff --git a/examples/plugins/tauri-plugin-example/src/lib.rs b/examples/plugins/tauri-plugin-example/src/lib.rs index 7d12d9af8195..3b9acffd5adb 100644 --- a/examples/plugins/tauri-plugin-example/src/lib.rs +++ b/examples/plugins/tauri-plugin-example/src/lib.rs @@ -1,14 +1,14 @@ pub fn add(left: usize, right: usize) -> usize { - left + right + left + right } #[cfg(test)] mod tests { - use super::*; + use super::*; - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } } From 77ae62180b955d861a24e1f42696f2ee5a396845 Mon Sep 17 00:00:00 2001 From: Chip Reed Date: Tue, 12 Dec 2023 18:21:56 +0900 Subject: [PATCH 03/69] move command module to its own directory --- core/tauri/src/{command.rs => command/mod.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename core/tauri/src/{command.rs => command/mod.rs} (100%) diff --git a/core/tauri/src/command.rs b/core/tauri/src/command/mod.rs similarity index 100% rename from core/tauri/src/command.rs rename to core/tauri/src/command/mod.rs From e60d8a9664bf5314d8d57802e8e925d21122d6f9 Mon Sep 17 00:00:00 2001 From: Chip Reed Date: Mon, 18 Dec 2023 22:17:56 +0900 Subject: [PATCH 04/69] wip: new command traits and generated code --- core/tauri-macros/src/lib.rs | 2 +- core/tauri-macros/src/runtime.rs | 43 ++++++- core/tauri-utils/Cargo.toml | 3 +- core/tauri-utils/src/acl/capability.rs | 35 ++++++ core/tauri-utils/src/acl/mod.rs | 12 +- core/tauri-utils/src/acl/resolved.rs | 45 +++++++ core/tauri-utils/src/acl/value.rs | 18 ++- core/tauri/Cargo.toml | 1 + core/tauri/src/command/authority.rs | 161 +++++++++++++++++++++++++ core/tauri/src/command/mod.rs | 2 + 10 files changed, 310 insertions(+), 12 deletions(-) create mode 100644 core/tauri-utils/src/acl/capability.rs create mode 100644 core/tauri-utils/src/acl/resolved.rs create mode 100644 core/tauri/src/command/authority.rs diff --git a/core/tauri-macros/src/lib.rs b/core/tauri-macros/src/lib.rs index 990dc6aff0fa..70dcfa1e0b91 100644 --- a/core/tauri-macros/src/lib.rs +++ b/core/tauri-macros/src/lib.rs @@ -87,7 +87,7 @@ pub fn generate_context(items: TokenStream) -> TokenStream { #[proc_macro_attribute] pub fn default_runtime(attributes: TokenStream, input: TokenStream) -> TokenStream { let attributes = parse_macro_input!(attributes as runtime::Attributes); - let input = parse_macro_input!(input as DeriveInput); + let input = parse_macro_input!(input as runtime::Input); runtime::default_runtime(attributes, input).into() } diff --git a/core/tauri-macros/src/runtime.rs b/core/tauri-macros/src/runtime.rs index 800e6beb399a..24d920e937b9 100644 --- a/core/tauri-macros/src/runtime.rs +++ b/core/tauri-macros/src/runtime.rs @@ -3,9 +3,42 @@ // SPDX-License-Identifier: MIT use proc_macro2::TokenStream; -use quote::quote; +use quote::{quote, ToTokens}; use syn::parse::{Parse, ParseStream}; -use syn::{parse_quote, DeriveInput, GenericParam, Ident, Token, Type, TypeParam}; +use syn::{parse_quote, DeriveInput, GenericParam, Ident, ItemTrait, Token, Type, TypeParam}; + +#[derive(Clone)] +pub(crate) enum Input { + Derive(DeriveInput), + Trait(ItemTrait), +} + +impl Parse for Input { + fn parse(input: ParseStream) -> syn::Result { + input + .parse::() + .map(Self::Derive) + .or_else(|_| input.parse::().map(Self::Trait)) + } +} + +impl Input { + fn last_param_mut(&mut self) -> Option<&mut GenericParam> { + match self { + Input::Derive(d) => d.generics.params.last_mut(), + Input::Trait(t) => t.generics.params.last_mut(), + } + } +} + +impl ToTokens for Input { + fn to_tokens(&self, tokens: &mut TokenStream) { + match self { + Input::Derive(d) => d.to_tokens(tokens), + Input::Trait(t) => t.to_tokens(tokens), + } + } +} /// The default runtime type to enable when the provided feature is enabled. pub(crate) struct Attributes { @@ -24,13 +57,11 @@ impl Parse for Attributes { } } -pub(crate) fn default_runtime(attributes: Attributes, input: DeriveInput) -> TokenStream { +pub(crate) fn default_runtime(attributes: Attributes, input: Input) -> TokenStream { // create a new copy to manipulate for the wry feature flag let mut wry = input.clone(); let wry_runtime = wry - .generics - .params - .last_mut() + .last_param_mut() .expect("default_runtime requires the item to have at least 1 generic parameter"); // set the default value of the last generic parameter to the provided runtime type diff --git a/core/tauri-utils/Cargo.toml b/core/tauri-utils/Cargo.toml index ffa5f269cbb6..96bac4ba634c 100644 --- a/core/tauri-utils/Cargo.toml +++ b/core/tauri-utils/Cargo.toml @@ -30,7 +30,7 @@ getrandom = { version = "0.2", optional = true, features = [ "std" ] } serialize-to-javascript = { version = "=0.1.1", optional = true } ctor = "0.2" json5 = { version = "0.4", optional = true } -toml = { version = "0.8", default-features = true } +toml = { version = "0.8", features = ["parse"] } json-patch = "1.2" glob = { version = "0.3", optional = true } walkdir = { version = "2", optional = true } @@ -39,6 +39,7 @@ semver = "1" infer = "0.15" dunce = "1" log = "0.4.20" +matchit = "0.7" [target."cfg(target_os = \"linux\")".dependencies] heck = "0.4" diff --git a/core/tauri-utils/src/acl/capability.rs b/core/tauri-utils/src/acl/capability.rs new file mode 100644 index 000000000000..16065484f7e6 --- /dev/null +++ b/core/tauri-utils/src/acl/capability.rs @@ -0,0 +1,35 @@ +use crate::acl::PermissionId; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CapabilityId { + inner: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] + +pub struct CapabilitySet { + inner: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Capability { + identifier: CapabilityId, + description: String, + #[serde(default)] + context: CapabilityContext, + windows: Vec, + permissions: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum CapabilityContext { + Local, + Remote { dangerous_remote: Vec }, +} + +impl Default for CapabilityContext { + fn default() -> Self { + Self::Local + } +} diff --git a/core/tauri-utils/src/acl/mod.rs b/core/tauri-utils/src/acl/mod.rs index f2bc29a7a402..a1b1d4f8cd19 100644 --- a/core/tauri-utils/src/acl/mod.rs +++ b/core/tauri-utils/src/acl/mod.rs @@ -1,10 +1,13 @@ +use serde::{Deserialize, Serialize}; use std::num::NonZeroU64; pub use self::{identifier::*, value::*}; -mod identifier; +pub mod capability; +pub mod identifier; pub mod plugin; -mod value; +pub mod resolved; +pub mod value; /// Allowed and denied commands inside a permission. /// @@ -42,6 +45,11 @@ pub struct InlinedPermission { scopes: Scopes, } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct PermissionId { + inner: String, +} + /// A permission. #[derive(Debug)] pub struct Permission { diff --git a/core/tauri-utils/src/acl/resolved.rs b/core/tauri-utils/src/acl/resolved.rs new file mode 100644 index 000000000000..42ef296bc273 --- /dev/null +++ b/core/tauri-utils/src/acl/resolved.rs @@ -0,0 +1,45 @@ +use matchit::Router; +use serde::de::DeserializeOwned; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; + +/// TODO: the current proof of concept uses [`matchit`], but we should use a simplified +/// router router that __only__ supports static and wildcard values (without wildcard params) +pub struct WindowMatcher { + inner: Router, +} + +pub struct WindowMatch { + inner: BTreeMap, +} + +pub enum ResolvedCommand { + Deny, + Allow(ResolvedScopes), +} + +pub enum ScopeKind<'de, T> +where + T: Serialize + Deserialize<'de>, +{ + Allow(&'de T), + Deny(&'de T), +} + +pub struct ResolvedScopes +where + T: Serialize, + for<'de> T: Deserialize<'de>, +{ + allow: Vec, + deny: Vec, +} + +impl ResolvedScopes +where + T: Serialize + DeserializeOwned, + for<'de> T: Deserialize<'de>, +{ +} + +pub struct Resolved {} diff --git a/core/tauri-utils/src/acl/value.rs b/core/tauri-utils/src/acl/value.rs index 368c216a104f..db7d632f04d7 100644 --- a/core/tauri-utils/src/acl/value.rs +++ b/core/tauri-utils/src/acl/value.rs @@ -1,7 +1,11 @@ use std::collections::BTreeMap; +use serde::de::DeserializeOwned; +use serde::{Deserialize, Serialize}; + /// A valid ACL number. -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialOrd, PartialEq)] +#[serde(untagged)] pub enum Number { /// Represents an [`i64`]. Int(i64), @@ -25,7 +29,8 @@ impl From for Number { } /// All supported ACL values. -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialOrd, PartialEq)] +#[serde(untagged)] pub enum Value { /// Represents a [`bool`]. Bool(bool), @@ -43,6 +48,15 @@ pub enum Value { Map(BTreeMap), } +impl Value { + /// TODO: implement [`serde::Deserializer`] directly to avoid serializing then deserializing + pub fn deserialize(&self) -> Option { + toml::to_string(self) + .ok() + .and_then(|s| toml::from_str(&s).ok()) + } +} + impl From for Value { #[inline(always)] fn from(value: bool) -> Self { diff --git a/core/tauri/Cargo.toml b/core/tauri/Cargo.toml index 35409c41469b..685b08d73a72 100644 --- a/core/tauri/Cargo.toml +++ b/core/tauri/Cargo.toml @@ -70,6 +70,7 @@ infer = { version = "0.15", optional = true } png = { version = "0.17", optional = true } ico = { version = "0.3.0", optional = true } http-range = { version = "0.1.5", optional = true } +static_assertions = "1.1.0" [target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\", target_os = \"windows\", target_os = \"macos\"))".dependencies] muda = { version = "0.11", default-features = false, features = [ "serde" ] } diff --git a/core/tauri/src/command/authority.rs b/core/tauri/src/command/authority.rs new file mode 100644 index 000000000000..88457cfae93d --- /dev/null +++ b/core/tauri/src/command/authority.rs @@ -0,0 +1,161 @@ +use std::collections::BTreeMap; +use std::sync::{Arc, Mutex}; + +use serde::de::DeserializeOwned; +use serde::Deserialize; +use state::TypeMap; + +use tauri_macros::default_runtime; +use tauri_utils::acl::Value; + +use crate::command; +use crate::command::{CommandArg, CommandItem}; +use crate::ipc::InvokeMessage; +use crate::Runtime; + +pub struct Caps; + +pub struct RuntimeAuthority { + caps: Caps, + cmds: (), +} + +pub enum CommandError {} +pub trait IntoCommandResponse {} + +pub struct RuntimeAuthorityScope { + raw: BTreeMap, + cache: TypeMap![Send + Sync], +} + +impl RuntimeAuthorityScope { + pub fn get_typed(&self, key: &str) -> Option<&T> { + match self.cache.try_get() { + cached @ Some(_) => cached, + None => match self.raw.get(key).and_then(Value::deserialize::) { + None => None, + Some(value) => { + let _ = self.cache.set(value); + self.cache.try_get() + } + }, + } + } +} + +macro_rules! command { + ($command:ident) => { + $command!() + }; +} + +#[command] +fn test(string: String) -> String { + string +} + +macro_rules! test { + () => {{ + struct Cmd; + + impl StrictCommand for Cmd { + const ID: &'static str = "test"; + + type Scope = WeakScope; + + fn handle( + &self, + _scope: &Self::Scope, + request: CommandRequest, + ) -> Result<(), CommandError> { + let arg1 = CommandArg::from_command(CommandItem { + name: "test", + key: "string", + message: &request.msg, + }) + .unwrap(); + + test(arg1); + + Ok(()) + } + } + + Box::new(Cmd) + }}; +} + +trait Scoped: Send + Sync + DeserializeOwned {} + +#[derive(Debug, Deserialize)] +struct WeakScope; + +impl Scoped for WeakScope {} + +impl Scoped for () {} + +#[default_runtime(crate::Wry, wry)] +struct CommandRequest { + scope: Arc, + msg: InvokeMessage, +} + +struct CommandResponse; + +static_assertions::assert_obj_safe!(Command); +#[default_runtime(crate::Wry, wry)] +trait Command { + fn name(&self) -> &'static str; + + fn handle(&self, request: CommandRequest) -> Result<(), CommandError>; +} + +#[default_runtime(crate::Wry, wry)] +trait StrictCommand { + const ID: &'static str; + + type Scope: Scoped + 'static; + + fn handle(&self, scope: &Self::Scope, request: CommandRequest) -> Result<(), CommandError>; +} + +impl Command for T +where + R: Runtime, + T: StrictCommand, +{ + fn name(&self) -> &'static str { + T::ID + } + + fn handle(&self, request: CommandRequest) -> Result<(), CommandError> { + let scopes = request.scope.clone(); + let scope = scopes.get_typed::(T::ID).unwrap(); + self.handle(scope, request) + } +} + +/* +/// Represents any item that can be turned into a command. +pub trait CommandHandler { + fn handle(&self, invoke: InvokeMessage); +}*/ + +struct MyCommand { + inner: Arc>, +} + +impl StrictCommand for MyCommand { + const ID: &'static str = "my_command"; + type Scope = (); + + fn handle(&self, _scope: &Self::Scope, request: CommandRequest) -> Result<(), CommandError> { + self.inner.lock().unwrap(); + + Ok(()) + } +} + +fn asdf() { + let _: &[Box + Send + Sync>] = &[command!(test)]; +} diff --git a/core/tauri/src/command/mod.rs b/core/tauri/src/command/mod.rs index f3da5359dcf5..ff63c2b177c4 100644 --- a/core/tauri/src/command/mod.rs +++ b/core/tauri/src/command/mod.rs @@ -16,6 +16,8 @@ use serde::{ Deserialize, Deserializer, }; +pub mod authority; + /// Represents a custom command. pub struct CommandItem<'a, R: Runtime> { /// The name of the command, e.g. `handler` on `#[command] fn handler(value: u64)` From 8ccf567e090ea41f1feb95365efe48b2317691ac Mon Sep 17 00:00:00 2001 From: Chip Reed Date: Thu, 21 Dec 2023 13:58:13 +0900 Subject: [PATCH 05/69] wip: whip --- core/tauri-macros/src/command2.rs | 5 + core/tauri-macros/src/lib.rs | 6 + core/tauri-utils/src/acl/value.rs | 7 +- core/tauri/Cargo.toml | 1 + core/tauri/src/command/authority.rs | 166 ++++++++++++++++++++-------- core/tauri/src/command/mod.rs | 5 +- core/tauri/src/lib.rs | 5 + 7 files changed, 141 insertions(+), 54 deletions(-) create mode 100644 core/tauri-macros/src/command2.rs diff --git a/core/tauri-macros/src/command2.rs b/core/tauri-macros/src/command2.rs new file mode 100644 index 000000000000..7af3a66d66d8 --- /dev/null +++ b/core/tauri-macros/src/command2.rs @@ -0,0 +1,5 @@ +use proc_macro::TokenStream; + +pub fn wrapper(attributes: TokenStream, item: TokenStream) -> TokenStream { + todo!() +} diff --git a/core/tauri-macros/src/lib.rs b/core/tauri-macros/src/lib.rs index 70dcfa1e0b91..21297b37af52 100644 --- a/core/tauri-macros/src/lib.rs +++ b/core/tauri-macros/src/lib.rs @@ -16,6 +16,7 @@ use proc_macro::TokenStream; use syn::{parse_macro_input, DeriveInput}; mod command; +mod command2; mod menu; mod mobile; mod runtime; @@ -34,6 +35,11 @@ pub fn command(attributes: TokenStream, item: TokenStream) -> TokenStream { command::wrapper(attributes, item) } +#[proc_macro_attribute] +pub fn command2(attributes: TokenStream, item: TokenStream) -> TokenStream { + command2::wrapper(attributes, item) +} + #[proc_macro_attribute] pub fn mobile_entry_point(attributes: TokenStream, item: TokenStream) -> TokenStream { mobile::entry_point(attributes, item) diff --git a/core/tauri-utils/src/acl/value.rs b/core/tauri-utils/src/acl/value.rs index db7d632f04d7..cb5d8f49704f 100644 --- a/core/tauri-utils/src/acl/value.rs +++ b/core/tauri-utils/src/acl/value.rs @@ -1,4 +1,5 @@ use std::collections::BTreeMap; +use std::fmt::Debug; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; @@ -50,10 +51,10 @@ pub enum Value { impl Value { /// TODO: implement [`serde::Deserializer`] directly to avoid serializing then deserializing - pub fn deserialize(&self) -> Option { - toml::to_string(self) + pub fn deserialize(&self) -> Option { + dbg!(toml::to_string(self)) .ok() - .and_then(|s| toml::from_str(&s).ok()) + .and_then(|s| dbg!(toml::from_str(&s).ok())) } } diff --git a/core/tauri/Cargo.toml b/core/tauri/Cargo.toml index 685b08d73a72..717062620617 100644 --- a/core/tauri/Cargo.toml +++ b/core/tauri/Cargo.toml @@ -71,6 +71,7 @@ png = { version = "0.17", optional = true } ico = { version = "0.3.0", optional = true } http-range = { version = "0.1.5", optional = true } static_assertions = "1.1.0" +toml = "0.8.8" [target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\", target_os = \"windows\", target_os = \"macos\"))".dependencies] muda = { version = "0.11", default-features = false, features = [ "serde" ] } diff --git a/core/tauri/src/command/authority.rs b/core/tauri/src/command/authority.rs index 88457cfae93d..9dcea7d2c8e8 100644 --- a/core/tauri/src/command/authority.rs +++ b/core/tauri/src/command/authority.rs @@ -1,17 +1,21 @@ use std::collections::BTreeMap; -use std::sync::{Arc, Mutex}; +use std::fmt::Debug; +use std::marker::PhantomData; +use std::sync::{Arc, Mutex, RwLock}; use serde::de::DeserializeOwned; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use state::TypeMap; +use serde_json::Value; use tauri_macros::default_runtime; -use tauri_utils::acl::Value; use crate::command; -use crate::command::{CommandArg, CommandItem}; use crate::ipc::InvokeMessage; -use crate::Runtime; +use crate::{Runtime, RuntimeHandle}; + +/// Alias for `Result`. +pub type Result = ::std::result::Result; pub struct Caps; @@ -20,19 +24,32 @@ pub struct RuntimeAuthority { cmds: (), } -pub enum CommandError {} -pub trait IntoCommandResponse {} +#[derive(Debug)] +pub enum Error { + NotFound, +} + +pub trait IntoCommandResponse { + fn into_command_response(self) -> CommandResponse; +} +#[derive(Debug, Default)] pub struct RuntimeAuthorityScope { raw: BTreeMap, cache: TypeMap![Send + Sync], } impl RuntimeAuthorityScope { - pub fn get_typed(&self, key: &str) -> Option<&T> { + pub fn get_typed(&self, key: &str) -> Option<&T> { match self.cache.try_get() { cached @ Some(_) => cached, - None => match self.raw.get(key).and_then(Value::deserialize::) { + //None => match dbg!(self.raw.get(key).and_then(Value::deserialize::)) { + None => match self + .raw + .get(key) + .and_then(|r| dbg!(serde_json::from_value::(dbg!(r.clone()))).ok()) + //.and_then(|r| dbg!(serde_json::from_str::(&r)).ok()) + { None => None, Some(value) => { let _ = self.cache.set(value); @@ -58,16 +75,19 @@ macro_rules! test { () => {{ struct Cmd; - impl StrictCommand for Cmd { - const ID: &'static str = "test"; - + impl StrictCommand for Cmd { type Scope = WeakScope; + type Response = CommandResponse; + + fn name(&self) -> &'static str { + "test" + } fn handle( &self, _scope: &Self::Scope, request: CommandRequest, - ) -> Result<(), CommandError> { + ) -> Result { let arg1 = CommandArg::from_command(CommandItem { name: "test", key: "string", @@ -77,7 +97,7 @@ macro_rules! test { test(arg1); - Ok(()) + Ok(CommandResponse) } } @@ -94,68 +114,118 @@ impl Scoped for WeakScope {} impl Scoped for () {} -#[default_runtime(crate::Wry, wry)] -struct CommandRequest { +impl<'a> TryFrom<&'a RuntimeAuthorityScope> for &'a WeakScope { + type Error = Error; + + fn try_from(value: &'a RuntimeAuthorityScope) -> ::std::result::Result { + value.get_typed("weak-scope").ok_or(Error::NotFound) + } +} + +#[default_runtime(crate::WryHandle, wry)] +struct CommandRequest { scope: Arc, - msg: InvokeMessage, + //msg: InvokeMessage, + _m: PhantomData, } -struct CommandResponse; +struct CommandResponse(String); + +impl IntoCommandResponse for S +where + S: Serialize, +{ + fn into_command_response(self: S) -> CommandResponse { + CommandResponse(serde_json::to_string(&self).unwrap()) + } +} static_assertions::assert_obj_safe!(Command); -#[default_runtime(crate::Wry, wry)] -trait Command { +#[default_runtime(crate::WryHandle, wry)] +trait Command { fn name(&self) -> &'static str; - fn handle(&self, request: CommandRequest) -> Result<(), CommandError>; + fn handler(&self) -> fn(CommandRequest) -> Result; + + //fn handle(&self, request: CommandRequest) -> Result; } -#[default_runtime(crate::Wry, wry)] -trait StrictCommand { - const ID: &'static str; +#[default_runtime(crate::WryHandle, wry)] +trait StrictCommand { + type Scope: Scoped + Debug + 'static; + type Response: IntoCommandResponse; - type Scope: Scoped + 'static; + fn name() -> &'static str; - fn handle(&self, scope: &Self::Scope, request: CommandRequest) -> Result<(), CommandError>; + fn handle(scope: &Self::Scope, request: CommandRequest) -> Result; +} + +fn strict_handler>( + request: CommandRequest, +) -> Result { + let scopes = dbg!(request.scope.clone()); + let scope = dbg!(scopes.get_typed::(T::name())).unwrap(); + T::handle(scope, request).map(IntoCommandResponse::into_command_response) } impl Command for T where - R: Runtime, + R: RuntimeHandle, T: StrictCommand, { fn name(&self) -> &'static str { - T::ID + T::name() } - fn handle(&self, request: CommandRequest) -> Result<(), CommandError> { - let scopes = request.scope.clone(); - let scope = scopes.get_typed::(T::ID).unwrap(); - self.handle(scope, request) + fn handler(&self) -> fn(CommandRequest) -> Result { + strict_handler:: } } -/* -/// Represents any item that can be turned into a command. -pub trait CommandHandler { - fn handle(&self, invoke: InvokeMessage); -}*/ +struct Echo; -struct MyCommand { - inner: Arc>, -} +impl Scoped for String {} -impl StrictCommand for MyCommand { - const ID: &'static str = "my_command"; - type Scope = (); +impl StrictCommand for Echo { + type Scope = String; + type Response = String; - fn handle(&self, _scope: &Self::Scope, request: CommandRequest) -> Result<(), CommandError> { - self.inner.lock().unwrap(); + fn name() -> &'static str { + "echo" + } - Ok(()) + fn handle(scope: &Self::Scope, request: CommandRequest) -> Result { + assert_eq!(scope, "ECHO"); + Ok("THIS IS AN ECHO".into()) } } -fn asdf() { - let _: &[Box + Send + Sync>] = &[command!(test)]; +#[cfg(test)] +mod tests { + use super::*; + use crate::EventLoopMessage; + use tauri_runtime_wry::WryHandle; + + #[tokio::test] + async fn echo() { + let cmd: Box + Send + Sync> = Box::new(Echo); + let request: CommandRequest = CommandRequest { + scope: Arc::new(RuntimeAuthorityScope { + raw: [(cmd.name().into(), Value::String("ECHO".into()))].into(), + cache: Default::default(), + }), + _m: PhantomData::default(), + }; + let handler = dbg!(cmd.handler()); + + assert_eq!(cmd.name(), "echo"); + crate::async_runtime::spawn(async move { + assert_eq!( + handler(request).unwrap().0, + String::from("\"THIS IS AN ECHO\"") + ); + }) + .await + .unwrap(); + } } diff --git a/core/tauri/src/command/mod.rs b/core/tauri/src/command/mod.rs index ff63c2b177c4..0abaae4db055 100644 --- a/core/tauri/src/command/mod.rs +++ b/core/tauri/src/command/mod.rs @@ -55,9 +55,8 @@ pub trait CommandArg<'de, R: Runtime>: Sized { /// Automatically implement [`CommandArg`] for any type that can be deserialized. impl<'de, D: Deserialize<'de>, R: Runtime> CommandArg<'de, R> for D { fn from_command(command: CommandItem<'de, R>) -> Result { - let name = command.name; - let arg = command.key; - Self::deserialize(command).map_err(|e| crate::Error::InvalidArgs(name, arg, e).into()) + let CommandItem { name, key, .. } = command; + Self::deserialize(command).map_err(|e| crate::Error::InvalidArgs(name, key, e).into()) } } diff --git a/core/tauri/src/lib.rs b/core/tauri/src/lib.rs index 59a197ff93dd..7b812521411e 100644 --- a/core/tauri/src/lib.rs +++ b/core/tauri/src/lib.rs @@ -109,6 +109,9 @@ pub use http; #[cfg(feature = "wry")] #[cfg_attr(docsrs, doc(cfg(feature = "wry")))] pub type Wry = tauri_runtime_wry::Wry; +#[cfg(feature = "wry")] +#[cfg_attr(docsrs, doc(cfg(feature = "wry")))] +pub type WryHandle = tauri_runtime_wry::WryHandle; #[cfg(all(feature = "wry", target_os = "android"))] #[cfg_attr(docsrs, doc(cfg(all(feature = "wry", target_os = "android"))))] @@ -274,8 +277,10 @@ pub enum EventLoopMessage { /// The webview runtime interface. A wrapper around [`runtime::Runtime`] with the proper user event type associated. pub trait Runtime: runtime::Runtime {} +pub trait RuntimeHandle: runtime::RuntimeHandle {} impl> Runtime for W {} +impl> RuntimeHandle for R {} /// Reads the config file at compile time and generates a [`Context`] based on its content. /// From ba778d31d939a1f7ec5c390548832b4c3457318e Mon Sep 17 00:00:00 2001 From: Chip Reed Date: Thu, 21 Dec 2023 20:00:19 +0900 Subject: [PATCH 06/69] wip: static dispatch there is a man standing behind me --- core/tauri-macros/src/runtime.rs | 17 +++- core/tauri/src/command/authority.rs | 129 ++++++++++++++++++++++++++-- 2 files changed, 136 insertions(+), 10 deletions(-) diff --git a/core/tauri-macros/src/runtime.rs b/core/tauri-macros/src/runtime.rs index 24d920e937b9..fbe74aa0ccc9 100644 --- a/core/tauri-macros/src/runtime.rs +++ b/core/tauri-macros/src/runtime.rs @@ -5,12 +5,16 @@ use proc_macro2::TokenStream; use quote::{quote, ToTokens}; use syn::parse::{Parse, ParseStream}; -use syn::{parse_quote, DeriveInput, GenericParam, Ident, ItemTrait, Token, Type, TypeParam}; +use syn::{ + parse_quote, DeriveInput, Error, GenericParam, Ident, ItemFn, ItemTrait, ItemType, Token, Type, + TypeParam, +}; #[derive(Clone)] pub(crate) enum Input { Derive(DeriveInput), Trait(ItemTrait), + Type(ItemType), } impl Parse for Input { @@ -18,7 +22,14 @@ impl Parse for Input { input .parse::() .map(Self::Derive) - .or_else(|_| input.parse::().map(Self::Trait)) + .or_else(|_| input.parse().map(Self::Trait)) + .or_else(|_| input.parse().map(Self::Type)) + .map_err(|_| { + Error::new( + input.span(), + "default_runtime only supports `struct`, `enum`, `type`, or `trait` definitions", + ) + }) } } @@ -27,6 +38,7 @@ impl Input { match self { Input::Derive(d) => d.generics.params.last_mut(), Input::Trait(t) => t.generics.params.last_mut(), + Input::Type(t) => t.generics.params.last_mut(), } } } @@ -36,6 +48,7 @@ impl ToTokens for Input { match self { Input::Derive(d) => d.to_tokens(tokens), Input::Trait(t) => t.to_tokens(tokens), + Input::Type(t) => t.to_tokens(tokens), } } } diff --git a/core/tauri/src/command/authority.rs b/core/tauri/src/command/authority.rs index 9dcea7d2c8e8..a6e01d3449cb 100644 --- a/core/tauri/src/command/authority.rs +++ b/core/tauri/src/command/authority.rs @@ -1,6 +1,9 @@ +use std::any::Any; use std::collections::BTreeMap; use std::fmt::Debug; +use std::future::{Future, Ready}; use std::marker::PhantomData; +use std::pin::Pin; use std::sync::{Arc, Mutex, RwLock}; use serde::de::DeserializeOwned; @@ -17,6 +20,9 @@ use crate::{Runtime, RuntimeHandle}; /// Alias for `Result`. pub type Result = ::std::result::Result; +#[default_runtime(crate::WryHandle, wry)] +pub type CommandHandle = fn(Box, CommandRequest) -> Result; + pub struct Caps; pub struct RuntimeAuthority { @@ -200,22 +206,129 @@ impl StrictCommand for Echo { } } +pub type VCmdState = Arc; + +#[default_runtime(crate::WryHandle, wry)] +pub type VCmdHandle = fn(Option, CommandRequest) -> VCmdFuture; + +#[default_runtime(crate::WryHandle, wry)] +pub type VCmdSetup = fn(&VCmd); + +pub type VCmdFuture = Pin> + Send>>; + +/*#[default_runtime(crate::WryHandle, wry)] +pub struct VCmdHandler { + state: Option, + setup: Option) -> Ready<()>>, + handle: VCmdHandle, +} + +impl VCmdHandler { + pub async fn handle(self, request: CommandRequest) -> Result { + if let Some(setup) = self.setup { + setup(self.state.as_ref()).await + } + + (self.handle)(self.state, request).await + } +}*/ + +#[default_runtime(crate::WryHandle, wry)] +pub struct VCmd { + pub name: &'static str, + pub state: Option, + pub setup: Option) -> Ready<()>>, + pub handle: VCmdHandle, +} + +impl Clone for VCmd +where + R: RuntimeHandle, +{ + #[inline(always)] + fn clone(&self) -> Self { + Self { + name: self.name, + state: self.state.clone(), + setup: self.setup, + handle: self.handle, + } + } +} + +impl VCmd { + #[inline(always)] + fn setup(&self) -> Self { + VCmd { + name: self.name, + state: self.state.clone(), + setup: self.setup, + handle: self.handle, + } + } + + pub async fn handle(self, request: CommandRequest) -> Result { + if let Some(setup) = self.setup { + setup(self.state.as_ref()).await + } + + (self.handle)(self.state, request).await + } +} + +#[default_runtime(crate::WryHandle, wry)] +pub struct VCmds(BTreeMap<&'static str, VCmd>); + +impl>>> From for VCmds { + fn from(value: T) -> Self { + Self(value.into()) + } +} + +fn echo() -> VCmd { + VCmd { + name: "echo", + state: None, + setup: None, + handle: |_, _r| Box::pin(async move { Ok(CommandResponse("THIS IS AN ECHO".into())) }), + } +} + #[cfg(test)] mod tests { use super::*; - use crate::EventLoopMessage; - use tauri_runtime_wry::WryHandle; - #[tokio::test] - async fn echo() { - let cmd: Box + Send + Sync> = Box::new(Echo); - let request: CommandRequest = CommandRequest { + fn req(scope: impl Into>) -> CommandRequest { + CommandRequest { scope: Arc::new(RuntimeAuthorityScope { - raw: [(cmd.name().into(), Value::String("ECHO".into()))].into(), + raw: scope.into(), cache: Default::default(), }), _m: PhantomData::default(), - }; + } + } + + #[tokio::test] + async fn echo_vcmd() { + let request = req([]); + let echo = super::echo(); + //let cmds = VCmds::from([(echo.name, echo)]); + + let handler = echo.clone(); + crate::async_runtime::spawn(async move { + assert_eq!( + handler.handle(request).await.unwrap().0, + String::from("THIS IS AN ECHO") + ); + }) + .await + .unwrap(); + } + + #[tokio::test] + async fn echo() { + let cmd: Box + Send + Sync> = Box::new(Echo); + let request = req([(cmd.name().into(), Value::String("ECHO".into()))]); let handler = dbg!(cmd.handler()); assert_eq!(cmd.name(), "echo"); From 1c5e822910f3e8521db5e10315d40edc3769cce0 Mon Sep 17 00:00:00 2001 From: Chip Reed Date: Thu, 4 Jan 2024 23:27:57 +0900 Subject: [PATCH 07/69] wip --- core/tauri/Cargo.toml | 1 + core/tauri/src/command/authority.rs | 255 ++++++++++++++++++++++------ 2 files changed, 204 insertions(+), 52 deletions(-) diff --git a/core/tauri/Cargo.toml b/core/tauri/Cargo.toml index 717062620617..2ac22d0e69f3 100644 --- a/core/tauri/Cargo.toml +++ b/core/tauri/Cargo.toml @@ -72,6 +72,7 @@ ico = { version = "0.3.0", optional = true } http-range = { version = "0.1.5", optional = true } static_assertions = "1.1.0" toml = "0.8.8" +async-trait = "0.1.74" [target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\", target_os = \"windows\", target_os = \"macos\"))".dependencies] muda = { version = "0.11", default-features = false, features = [ "serde" ] } diff --git a/core/tauri/src/command/authority.rs b/core/tauri/src/command/authority.rs index a6e01d3449cb..de8cbc2b0408 100644 --- a/core/tauri/src/command/authority.rs +++ b/core/tauri/src/command/authority.rs @@ -1,10 +1,10 @@ use std::any::Any; use std::collections::BTreeMap; use std::fmt::Debug; -use std::future::{Future, Ready}; +use std::future::{ready, Future}; use std::marker::PhantomData; use std::pin::Pin; -use std::sync::{Arc, Mutex, RwLock}; +use std::sync::Arc; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; @@ -14,7 +14,6 @@ use serde_json::Value; use tauri_macros::default_runtime; use crate::command; -use crate::ipc::InvokeMessage; use crate::{Runtime, RuntimeHandle}; /// Alias for `Result`. @@ -33,6 +32,9 @@ pub struct RuntimeAuthority { #[derive(Debug)] pub enum Error { NotFound, + StateEmpty, + StateType, + Scope, } pub trait IntoCommandResponse { @@ -132,10 +134,11 @@ impl<'a> TryFrom<&'a RuntimeAuthorityScope> for &'a WeakScope { struct CommandRequest { scope: Arc, //msg: InvokeMessage, + msg: String, _m: PhantomData, } -struct CommandResponse(String); +pub struct CommandResponse(String); impl IntoCommandResponse for S where @@ -206,73 +209,79 @@ impl StrictCommand for Echo { } } -pub type VCmdState = Arc; +pub type VCmdState = Arc; #[default_runtime(crate::WryHandle, wry)] pub type VCmdHandle = fn(Option, CommandRequest) -> VCmdFuture; -#[default_runtime(crate::WryHandle, wry)] -pub type VCmdSetup = fn(&VCmd); - pub type VCmdFuture = Pin> + Send>>; -/*#[default_runtime(crate::WryHandle, wry)] -pub struct VCmdHandler { +#[default_runtime(crate::WryHandle, wry)] +struct CommandInner { + name: &'static str, state: Option, - setup: Option) -> Ready<()>>, handle: VCmdHandle, } -impl VCmdHandler { - pub async fn handle(self, request: CommandRequest) -> Result { - if let Some(setup) = self.setup { - setup(self.state.as_ref()).await - } - - (self.handle)(self.state, request).await - } -}*/ - -#[default_runtime(crate::WryHandle, wry)] -pub struct VCmd { - pub name: &'static str, - pub state: Option, - pub setup: Option) -> Ready<()>>, - pub handle: VCmdHandle, -} - -impl Clone for VCmd -where - R: RuntimeHandle, -{ +impl Clone for CommandInner { #[inline(always)] fn clone(&self) -> Self { Self { name: self.name, state: self.state.clone(), - setup: self.setup, handle: self.handle, } } } +#[default_runtime(crate::WryHandle, wry)] +pub struct VCmd { + inner: CommandInner, +} + impl VCmd { - #[inline(always)] - fn setup(&self) -> Self { - VCmd { - name: self.name, - state: self.state.clone(), - setup: self.setup, - handle: self.handle, + #[inline] + pub fn new(name: &'static str, handle: VCmdHandle) -> Self { + Self { + inner: CommandInner { + name, + handle, + state: None, + }, } } - pub async fn handle(self, request: CommandRequest) -> Result { - if let Some(setup) = self.setup { - setup(self.state.as_ref()).await + #[inline] + pub fn with_state(name: &'static str, handle: VCmdHandle, state: Arc) -> Self + where + T: Any + Send + Sync, + { + Self { + inner: CommandInner { + name, + handle, + state: Some(state), + }, } + } + + #[inline] + pub fn handler(&self) -> VCmdHandler { + VCmdHandler { + inner: self.inner.clone(), + } + } +} - (self.handle)(self.state, request).await +#[default_runtime(crate::WryHandle, wry)] +pub struct VCmdHandler { + inner: CommandInner, +} + +impl VCmdHandler { + #[inline(always)] + pub fn handle(self, request: CommandRequest) -> VCmdFuture { + (self.inner.handle)(self.inner.state, request) } } @@ -285,12 +294,121 @@ impl>>> From for VCm } } +#[default_runtime(crate::WryHandle, wry)] +pub trait IntoCommand: Sized { + fn into_command(self) -> VCmd; +} + +pub trait IntoCommandResult { + fn into_command_result(self) -> Result; +} + +impl IntoCommandResult for Result +where + T: IntoCommandResponse, +{ + #[inline(always)] + fn into_command_result(self) -> Result { + self.map(IntoCommandResponse::into_command_response) + } +} + +#[default_runtime(crate::WryHandle, wry)] +pub trait FunctionalCommand { + type Scope: Scoped + Debug + 'static; + + fn nname() -> &'static str; + + fn handle(scope: &Self::Scope, request: CommandRequest) -> VCmdFuture; + + fn into_command(self) -> VCmd + where + Self: Sized, + { + fn handle(_state: Option, request: CommandRequest) -> VCmdFuture + where + T: FunctionalCommand, + R: RuntimeHandle, + { + let scopes = request.scope.clone(); + let scope = scopes.get_typed::(T::nname()).unwrap(); + T::handle(scope, request) + } + + VCmd::new(Self::nname(), handle::) + } +} + +#[default_runtime(crate::WryHandle, wry)] +pub trait StatefulCommand { + type Scope: Scoped + Debug + 'static; + + fn nname() -> &'static str; + + fn handle(self: Arc, scope: &Self::Scope, request: CommandRequest) -> VCmdFuture; + + fn into_command(self) -> VCmd + where + Self: Send + Sync + Sized + 'static, + { + fn handle(state: Option, request: CommandRequest) -> VCmdFuture + where + T: StatefulCommand + Send + Sync + 'static, + R: RuntimeHandle, + { + Box::pin(async move { + let scopes = request.scope.clone(); + let scope = scopes + .get_typed::(T::nname()) + .ok_or(Error::Scope)?; + + let state = state + .ok_or(Error::StateEmpty)? + .downcast() + .map_err(|_| Error::StateType)?; + + T::handle(state, scope, request).await + }) + } + + VCmd::with_state(Self::nname(), handle::, Arc::new(self)) + } +} + fn echo() -> VCmd { - VCmd { - name: "echo", - state: None, - setup: None, - handle: |_, _r| Box::pin(async move { Ok(CommandResponse("THIS IS AN ECHO".into())) }), + VCmd::new("echo", |_, _r| { + Box::pin(async move { Ok(CommandResponse("THIS IS AN ECHO".into())) }) + }) +} + +struct E; + +impl FunctionalCommand for E { + type Scope = String; + + fn nname() -> &'static str { + "echo" + } + + fn handle(scope: &Self::Scope, request: CommandRequest) -> VCmdFuture { + Box::pin(ready(Ok(CommandResponse(request.msg)))) + } +} + +struct PE(String); + +impl StatefulCommand for PE { + type Scope = String; + + fn nname() -> &'static str { + "echo_prefix" + } + + fn handle(self: Arc, _: &Self::Scope, request: CommandRequest) -> VCmdFuture { + Box::pin(ready(Ok(CommandResponse(format!( + "{}: {}", + self.0, request.msg + ))))) } } @@ -304,7 +422,8 @@ mod tests { raw: scope.into(), cache: Default::default(), }), - _m: PhantomData::default(), + msg: "invoke message".into(), + _m: PhantomData, } } @@ -314,7 +433,7 @@ mod tests { let echo = super::echo(); //let cmds = VCmds::from([(echo.name, echo)]); - let handler = echo.clone(); + let handler = echo.handler(); crate::async_runtime::spawn(async move { assert_eq!( handler.handle(request).await.unwrap().0, @@ -325,6 +444,38 @@ mod tests { .unwrap(); } + #[tokio::test] + async fn echo_functional() { + let echo = E; + let request = req([("echo".into(), Value::String("ECHO".into()))]); + let cmd = echo.into_command(); + let handler = cmd.handler(); + crate::async_runtime::spawn(async move { + assert_eq!( + handler.handle(request).await.unwrap().0, + String::from("invoke message") + ); + }) + .await + .unwrap(); + } + + #[tokio::test] + async fn echo_stateful() { + let echo = PE("prefix".into()); + let request = req([("echo_prefix".into(), Value::String("ECHO".into()))]); + let cmd = echo.into_command(); + let handler = cmd.handler(); + crate::async_runtime::spawn(async move { + assert_eq!( + handler.handle(request).await.unwrap().0, + String::from("prefix: invoke message") + ); + }) + .await + .unwrap(); + } + #[tokio::test] async fn echo() { let cmd: Box + Send + Sync> = Box::new(Echo); From 022e7280234360774037ef90197229db195a66aa Mon Sep 17 00:00:00 2001 From: Chip Reed Date: Thu, 4 Jan 2024 06:32:36 -0800 Subject: [PATCH 08/69] re-add authority --- core/tauri/src/command/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/tauri/src/command/mod.rs b/core/tauri/src/command/mod.rs index 766e0186bc7d..ec766acfb3f0 100644 --- a/core/tauri/src/command/mod.rs +++ b/core/tauri/src/command/mod.rs @@ -16,6 +16,8 @@ use serde::{ Deserialize, Deserializer, }; +mod authority; + /// Represents a custom command. pub struct CommandItem<'a, R: Runtime> { /// The name of the command, e.g. `handler` on `#[command] fn handler(value: u64)` From d26fa6014d39c5fc15eb423391b26b27ee14d4b2 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Sat, 6 Jan 2024 10:26:46 -0300 Subject: [PATCH 09/69] fix build [skip ci] --- core/tauri/Cargo.toml | 1 + core/tauri/src/command/authority.rs | 4 +++- tooling/cli/Cargo.lock | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/core/tauri/Cargo.toml b/core/tauri/Cargo.toml index 36e8dd5d8338..d02067ac663b 100644 --- a/core/tauri/Cargo.toml +++ b/core/tauri/Cargo.toml @@ -71,6 +71,7 @@ png = { version = "0.17", optional = true } ico = { version = "0.3.0", optional = true } http-range = { version = "0.1.5", optional = true } tracing = { version = "0.1", optional = true } +static_assertions = "1" [target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\", target_os = \"windows\", target_os = \"macos\"))".dependencies] muda = { version = "0.11", default-features = false, features = [ "serde" ] } diff --git a/core/tauri/src/command/authority.rs b/core/tauri/src/command/authority.rs index de8cbc2b0408..11d84c543dc1 100644 --- a/core/tauri/src/command/authority.rs +++ b/core/tauri/src/command/authority.rs @@ -149,7 +149,6 @@ where } } -static_assertions::assert_obj_safe!(Command); #[default_runtime(crate::WryHandle, wry)] trait Command { fn name(&self) -> &'static str; @@ -159,6 +158,9 @@ trait Command { //fn handle(&self, request: CommandRequest) -> Result; } +#[cfg(feature = "wry")] +static_assertions::assert_obj_safe!(Command); + #[default_runtime(crate::WryHandle, wry)] trait StrictCommand { type Scope: Scoped + Debug + 'static; diff --git a/tooling/cli/Cargo.lock b/tooling/cli/Cargo.lock index b02b41f939fc..b05f4a7346d8 100644 --- a/tooling/cli/Cargo.lock +++ b/tooling/cli/Cargo.lock @@ -4884,6 +4884,7 @@ dependencies = [ "json5", "kuchikiki", "log", + "matchit", "memchr", "phf 0.11.2", "schemars", From 5db52172d9ff875a219f76bce14d69c2013f6dc4 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Sat, 6 Jan 2024 22:33:38 -0300 Subject: [PATCH 10/69] parse plugin permissions --- core/tauri-build/Cargo.toml | 1 + core/tauri-build/src/lib.rs | 1 + core/tauri-plugin/Cargo.toml | 9 +- core/tauri-plugin/src/build/acl.rs | 87 +++++++++++++++++++ core/tauri-plugin/src/build/mod.rs | 40 ++++++--- core/tauri-utils/src/acl/identifier.rs | 10 +++ core/tauri-utils/src/acl/mod.rs | 19 ++-- .../plugins/tauri-plugin-example/build.rs | 2 +- 8 files changed, 144 insertions(+), 25 deletions(-) create mode 100644 core/tauri-plugin/src/build/acl.rs diff --git a/core/tauri-build/Cargo.toml b/core/tauri-build/Cargo.toml index 8e59ac9a49c6..933172c6bb64 100644 --- a/core/tauri-build/Cargo.toml +++ b/core/tauri-build/Cargo.toml @@ -30,6 +30,7 @@ anyhow = "1" quote = { version = "1", optional = true } tauri-codegen = { version = "2.0.0-alpha.12", path = "../tauri-codegen", optional = true } tauri-utils = { version = "2.0.0-alpha.12", path = "../tauri-utils", features = [ "build", "resources" ] } +tauri-plugin = { version = "0.1.0", path = "../tauri-plugin", features = [ "build" ] } cargo_toml = "0.17" serde = "1" serde_json = "1" diff --git a/core/tauri-build/src/lib.rs b/core/tauri-build/src/lib.rs index a41793e3abc0..844a2243bf04 100644 --- a/core/tauri-build/src/lib.rs +++ b/core/tauri-build/src/lib.rs @@ -442,6 +442,7 @@ pub fn try_build(attributes: Attributes) -> Result<()> { } allowlist::check(&config, &mut manifest)?; + tauri_plugin::acl::read_permissions().context("failed to read plugin permissions")?; let target_triple = std::env::var("TARGET").unwrap(); diff --git a/core/tauri-plugin/Cargo.toml b/core/tauri-plugin/Cargo.toml index da6e314cebb4..1155ed1570c5 100644 --- a/core/tauri-plugin/Cargo.toml +++ b/core/tauri-plugin/Cargo.toml @@ -10,13 +10,16 @@ edition = { workspace = true } rust-version = { workspace = true } [features] -build = ["dep:anyhow", "dep:cargo_metadata", "dep:thiserror"] +build = ["dep:serde", "dep:cargo_metadata", "dep:thiserror", "dep:serde_json", "dep:glob", "dep:toml"] [dependencies] -anyhow = { version = "1", optional = true } +serde = { version = "1", optional = true } thiserror = { version = "1", optional = true } cargo_metadata = { version = "0.18", optional = true } -tauri = { version = "2.0.0-alpha.18", default-features = false, path = "../tauri" } +tauri-utils = { version = "2.0.0-alpha.12", default-features = false, path = "../tauri-utils" } +serde_json = { version = "1", optional = true } +glob = { version = "0.3", optional = true } +toml = { version = "0.8", optional = true } [package.metadata.docs.rs] features = ["build", "runtime"] diff --git a/core/tauri-plugin/src/build/acl.rs b/core/tauri-plugin/src/build/acl.rs new file mode 100644 index 000000000000..17f30e721c52 --- /dev/null +++ b/core/tauri-plugin/src/build/acl.rs @@ -0,0 +1,87 @@ +use std::{collections::HashMap, env::vars_os, path::PathBuf}; + +use super::Error; +use serde::Deserialize; +use tauri_utils::acl::{Identifier, Permission}; + +const PERMISSION_FILES_PATH_KEY: &str = "PERMISSION_FILES_PATH"; + +#[derive(Debug, Deserialize)] +pub struct PermissionSet { + /// A unique identifier for the permission. + pub identifier: Identifier, + + /// Human-readable description of what the permission does. + pub description: String, + + /// All permissions this set contains. + pub permissions: Vec, +} + +#[derive(Debug, Deserialize)] +pub struct PermissionFile { + pub default: Option, + pub set: Option>, + pub permission: Option>, +} + +pub fn define_permissions(pattern: &str) -> Result<(), Error> { + let permission_files = glob::glob(pattern)? + .flatten() + .map(|p| p.canonicalize()) + .flatten() + .collect::>(); + + let permission_files_path = std::env::temp_dir().join(format!( + "{}-permission-files", + std::env::var("CARGO_PKG_NAME").unwrap() + )); + std::fs::write( + &permission_files_path, + serde_json::to_string(&permission_files)?, + ) + .map_err(Error::WriteFile)?; + println!( + "cargo:{PERMISSION_FILES_PATH_KEY}={}", + permission_files_path.display() + ); + + Ok(()) +} + +pub fn read_permissions() -> Result>, Error> { + let mut permissions_map = HashMap::new(); + + for (key, value) in vars_os() { + let key = key.to_string_lossy(); + + if let Some(plugin_crate_name) = key + .strip_prefix("DEP_") + .and_then(|v| v.strip_suffix(&format!("_{PERMISSION_FILES_PATH_KEY}"))) + { + let permissions_path = PathBuf::from(value); + let permissions_str = std::fs::read_to_string(&permissions_path).map_err(Error::ReadFile)?; + let permissions: Vec = serde_json::from_str(&permissions_str)?; + let permissions = parse_permissions(permissions)?; + + permissions_map.insert(plugin_crate_name.to_lowercase(), permissions); + } + } + + Ok(permissions_map) +} + +fn parse_permissions(paths: Vec) -> Result, Error> { + let mut permissions = Vec::new(); + for path in paths { + let permission_file = std::fs::read_to_string(&path).map_err(Error::ReadFile)?; + let ext = path.extension().unwrap().to_string_lossy().to_string(); + let permission: PermissionFile = match ext.as_str() { + "toml" => toml::from_str(&permission_file)?, + "json" => serde_json::from_str(&permission_file)?, + _ => return Err(Error::UnknownPermissionFormat(ext)), + }; + permissions.push(permission); + } + Ok(permissions) +} diff --git a/core/tauri-plugin/src/build/mod.rs b/core/tauri-plugin/src/build/mod.rs index d8768cc58803..01cd133d6c3a 100644 --- a/core/tauri-plugin/src/build/mod.rs +++ b/core/tauri-plugin/src/build/mod.rs @@ -1,7 +1,8 @@ use cargo_metadata::{Metadata, MetadataCommand}; -use tauri::utils::acl::{Permission, PermissionSet}; use thiserror::Error; +pub mod acl; + #[derive(Debug, Error)] pub enum Error { #[error("expected build script env var {0}, but it was not found - ensure this is called in a build script")] @@ -21,13 +22,31 @@ pub enum Error { #[error("CARGO_MANIFEST_DIR could not canonicalize")] Manifest(std::io::Error), - #[error("failed to grab Cargo manifest: {0}")] + #[error("failed to read file: {0}")] + ReadFile(std::io::Error), + + #[error("failed to write file: {0}")] + WriteFile(std::io::Error), + + #[error("failed to execute: {0}")] Metadata(#[from] cargo_metadata::Error), + + #[error("failed to run glob: {0}")] + Glob(#[from] glob::PatternError), + + #[error("failed to parse TOML: {0}")] + Toml(#[from] toml::de::Error), + + #[error("failed to parse JSON: {0}")] + Json(#[from] serde_json::Error), + + #[error("unknown permission format {0}")] + UnknownPermissionFormat(String), } /// [`try_build`] but will exit automatically if an error is found. -pub fn build() { - if let Err(error) = try_build() { +pub fn build(permissions_path_pattern: &str) { + if let Err(error) = try_build(permissions_path_pattern) { println!("{}: {}", env!("CARGO_PKG_NAME"), error); std::process::exit(1); } @@ -39,7 +58,7 @@ pub fn build() { /// /// Errors will occur if environmental variables expected to be set inside of [build scripts] /// are not found, or if the crate violates Tauri plugin conventions. -pub fn try_build() -> Result<(), Error> { +pub fn try_build(permissions_path_pattern: &str) -> Result<(), Error> { // convention: plugin names should not use underscores let name = build_var("CARGO_PKG_NAME")?; if name.contains('_') { @@ -49,6 +68,8 @@ pub fn try_build() -> Result<(), Error> { // requirement: links MUST be set and MUST match the name let _links = build_var("CARGO_MANIFEST_LINKS")?; + acl::define_permissions(permissions_path_pattern)?; + let metadata = find_metadata()?; println!("{metadata:#?}"); @@ -71,12 +92,3 @@ fn find_metadata() -> Result { .map_err(Error::Metadata) }) } - -#[derive(Debug)] -struct PluginPermissions { - default: Permission, - sets: Option>, - permissions: Option>, -} - -impl PluginPermissions {} diff --git a/core/tauri-utils/src/acl/identifier.rs b/core/tauri-utils/src/acl/identifier.rs index 0e6a3fd992b3..a5c4007229b6 100644 --- a/core/tauri-utils/src/acl/identifier.rs +++ b/core/tauri-utils/src/acl/identifier.rs @@ -1,3 +1,4 @@ +use serde::{Deserialize, Deserializer}; use std::num::NonZeroU8; use thiserror::Error; @@ -166,6 +167,15 @@ impl TryFrom for Identifier { } } +impl<'de> Deserialize<'de> for Identifier { + fn deserialize(deserializer: D) -> std::result::Result + where + D: Deserializer<'de>, + { + Self::try_from(String::deserialize(deserializer)?).map_err(serde::de::Error::custom) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/core/tauri-utils/src/acl/mod.rs b/core/tauri-utils/src/acl/mod.rs index a1b1d4f8cd19..6f3e1c7b1dd3 100644 --- a/core/tauri-utils/src/acl/mod.rs +++ b/core/tauri-utils/src/acl/mod.rs @@ -12,22 +12,24 @@ pub mod value; /// Allowed and denied commands inside a permission. /// /// If two commands clash inside of `allow` and `deny`, it should be denied by default. -#[derive(Debug)] +#[derive(Debug, Default, Deserialize)] pub struct Commands { /// Allowed command. + #[serde(default)] pub allow: Vec, /// Denied command, which takes priority. + #[serde(default)] pub deny: Vec, } -#[derive(Debug)] +#[derive(Debug, Default, Deserialize)] pub struct Scopes { - allow: Value, - deny: Value, + allow: Option, + deny: Option, } -#[derive(Debug)] +#[derive(Debug, Deserialize)] pub struct InlinedPermission { /// The version of the permission. version: Option, @@ -39,9 +41,11 @@ pub struct InlinedPermission { description: Option, /// Allowed or denied commands when using this permission. + #[serde(default)] commands: Commands, /// Allowed or denied scoped when using this permission. + #[serde(default)] scopes: Scopes, } @@ -51,12 +55,13 @@ pub struct PermissionId { } /// A permission. -#[derive(Debug)] +#[derive(Debug, Deserialize)] pub struct Permission { + #[serde(flatten)] inner: InlinedPermission, } -#[derive(Debug)] +#[derive(Debug, Deserialize)] pub struct PermissionSet { /// A unique identifier for the permission. identifier: Identifier, diff --git a/examples/plugins/tauri-plugin-example/build.rs b/examples/plugins/tauri-plugin-example/build.rs index 4ffc371441c7..2ecf0ac89967 100644 --- a/examples/plugins/tauri-plugin-example/build.rs +++ b/examples/plugins/tauri-plugin-example/build.rs @@ -1,3 +1,3 @@ fn main() { - tauri_plugin::build() + tauri_plugin::build("./permissions/**/*.toml") } From 02268e4dc43fc723503f884b384556dd0e326b7a Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Sun, 7 Jan 2024 10:13:44 -0300 Subject: [PATCH 11/69] merge permission files [skip ci] --- core/tauri-build/src/acl.rs | 62 +++++++++ core/tauri-build/src/lib.rs | 9 +- core/tauri-plugin/src/build/acl.rs | 36 ++++- core/tauri-utils/src/acl/capability.rs | 18 ++- core/tauri-utils/src/acl/identifier.rs | 27 +++- core/tauri-utils/src/acl/mod.rs | 47 ++++--- core/tauri-utils/src/acl/plugin.rs | 14 ++ examples/api/src-tauri/Cargo.lock | 125 +++++++++++++----- .../src-tauri/tauri-plugin-sample/Cargo.toml | 1 + .../src-tauri/tauri-plugin-sample/build.rs | 2 + .../tauri-plugin-sample/permissions/ping.toml | 5 + .../plugins/tauri-plugin-example/Cargo.toml | 2 +- .../permissions/home-config.toml | 1 + .../permissions/home-dir.toml | 1 + 14 files changed, 290 insertions(+), 60 deletions(-) create mode 100644 core/tauri-build/src/acl.rs create mode 100644 examples/api/src-tauri/tauri-plugin-sample/permissions/ping.toml diff --git a/core/tauri-build/src/acl.rs b/core/tauri-build/src/acl.rs new file mode 100644 index 000000000000..e5448b026665 --- /dev/null +++ b/core/tauri-build/src/acl.rs @@ -0,0 +1,62 @@ +use std::collections::HashMap; + +use anyhow::{Context, Result}; +use tauri_utils::acl::{plugin::Manifest, InlinedPermission, Permission, PermissionSet}; + +pub fn process() -> Result> { + let permission_map = + tauri_plugin::acl::read_permissions().context("failed to read plugin permissions")?; + + let mut processed = HashMap::new(); + for (plugin_name, permission_files) in permission_map { + let mut manifest = Manifest { + default_permission: None, + permissions: HashMap::new(), + permission_sets: HashMap::new(), + }; + + for permission_file in permission_files { + if let Some(default) = permission_file.default { + manifest.default_permission.replace(Permission { + inner: InlinedPermission { + identifier: "default".into(), + version: default.version, + description: default.description, + commands: default.commands, + scopes: default.scopes, + }, + }); + } + + if let Some(permissions) = permission_file.permission { + manifest.permissions.extend( + permissions + .into_iter() + .map(|p| (p.inner.identifier.clone(), p)) + .collect::>(), + ); + } + if let Some(sets) = permission_file.set { + manifest.permission_sets.extend( + sets + .into_iter() + .map(|set| { + ( + set.identifier.clone(), + PermissionSet { + identifier: set.identifier, + description: set.description, + permissions: set.permissions, + }, + ) + }) + .collect::>(), + ); + } + } + + processed.insert(plugin_name, manifest); + } + + Ok(processed) +} diff --git a/core/tauri-build/src/lib.rs b/core/tauri-build/src/lib.rs index 844a2243bf04..8d91861f6c8b 100644 --- a/core/tauri-build/src/lib.rs +++ b/core/tauri-build/src/lib.rs @@ -27,6 +27,7 @@ use std::{ path::{Path, PathBuf}, }; +mod acl; mod allowlist; #[cfg(feature = "codegen")] mod codegen; @@ -40,6 +41,8 @@ mod static_vcruntime; #[cfg_attr(docsrs, doc(cfg(feature = "codegen")))] pub use codegen::context::CodegenContext; +const ACL_FILE_NAME: &str = "acl.json"; + fn copy_file(from: impl AsRef, to: impl AsRef) -> Result<()> { let from = from.as_ref(); let to = to.as_ref(); @@ -441,14 +444,16 @@ pub fn try_build(attributes: Attributes) -> Result<()> { Manifest::complete_from_path(&mut manifest, Path::new("Cargo.toml"))?; } + let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap()); + allowlist::check(&config, &mut manifest)?; - tauri_plugin::acl::read_permissions().context("failed to read plugin permissions")?; + let acl = acl::process()?; + std::fs::write(out_dir.join(ACL_FILE_NAME), serde_json::to_string(&acl)?)?; let target_triple = std::env::var("TARGET").unwrap(); println!("cargo:rustc-env=TAURI_ENV_TARGET_TRIPLE={target_triple}"); - let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap()); // TODO: far from ideal, but there's no other way to get the target dir, see let target_dir = out_dir .parent() diff --git a/core/tauri-plugin/src/build/acl.rs b/core/tauri-plugin/src/build/acl.rs index 17f30e721c52..1994fbad6362 100644 --- a/core/tauri-plugin/src/build/acl.rs +++ b/core/tauri-plugin/src/build/acl.rs @@ -1,15 +1,15 @@ -use std::{collections::HashMap, env::vars_os, path::PathBuf}; +use std::{collections::HashMap, env::vars_os, num::NonZeroU64, path::PathBuf}; use super::Error; use serde::Deserialize; -use tauri_utils::acl::{Identifier, Permission}; +use tauri_utils::acl::{Commands, Permission, Scopes}; const PERMISSION_FILES_PATH_KEY: &str = "PERMISSION_FILES_PATH"; #[derive(Debug, Deserialize)] pub struct PermissionSet { /// A unique identifier for the permission. - pub identifier: Identifier, + pub identifier: String, /// Human-readable description of what the permission does. pub description: String, @@ -18,9 +18,26 @@ pub struct PermissionSet { pub permissions: Vec, } +#[derive(Debug, Deserialize)] +pub struct DefaultPermission { + /// The version of the permission. + pub version: Option, + + /// Human-readable description of what the permission does. + pub description: Option, + + /// Allowed or denied commands when using this permission. + #[serde(default)] + pub commands: Commands, + + /// Allowed or denied scoped when using this permission. + #[serde(default)] + pub scopes: Scopes, +} + #[derive(Debug, Deserialize)] pub struct PermissionFile { - pub default: Option, + pub default: Option, pub set: Option>, pub permission: Option>, } @@ -55,7 +72,7 @@ pub fn read_permissions() -> Result>, Error> for (key, value) in vars_os() { let key = key.to_string_lossy(); - if let Some(plugin_crate_name) = key + if let Some(plugin_crate_name_var) = key .strip_prefix("DEP_") .and_then(|v| v.strip_suffix(&format!("_{PERMISSION_FILES_PATH_KEY}"))) { @@ -64,7 +81,14 @@ pub fn read_permissions() -> Result>, Error> let permissions: Vec = serde_json::from_str(&permissions_str)?; let permissions = parse_permissions(permissions)?; - permissions_map.insert(plugin_crate_name.to_lowercase(), permissions); + let plugin_crate_name = plugin_crate_name_var.to_lowercase().replace('_', "-"); + permissions_map.insert( + plugin_crate_name + .strip_prefix("tauri-plugin-") + .map(|n| n.to_string()) + .unwrap_or(plugin_crate_name), + permissions, + ); } } diff --git a/core/tauri-utils/src/acl/capability.rs b/core/tauri-utils/src/acl/capability.rs index 16065484f7e6..4b0e92f89300 100644 --- a/core/tauri-utils/src/acl/capability.rs +++ b/core/tauri-utils/src/acl/capability.rs @@ -1,6 +1,9 @@ +//! End-user abstraction for selecting permissions a window has access to. + use crate::acl::PermissionId; use serde::{Deserialize, Serialize}; +/// Identifier of a capability. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct CapabilityId { inner: String, @@ -8,10 +11,17 @@ pub struct CapabilityId { #[derive(Debug, Clone, Serialize, Deserialize)] +/// A set of direct capabilities grouped together under a new name. pub struct CapabilitySet { inner: Vec, } +/// a grouping and boundary mechanism developers can use to separate windows or plugins functionality from each other at runtime. +/// +/// If a window is not matching any capability then it has no access to the IPC layer at all. +/// +/// 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)] pub struct Capability { identifier: CapabilityId, @@ -22,10 +32,16 @@ pub struct Capability { permissions: Vec, } +/// Context of the capability. #[derive(Debug, Clone, Serialize, Deserialize)] pub enum CapabilityContext { + /// Capability refers to local URL usage. Local, - Remote { dangerous_remote: Vec }, + /// Capability refers to remote usage. + Remote { + /// Remote domain this capability refers to. + dangerous_remote: Vec, + }, } impl Default for CapabilityContext { diff --git a/core/tauri-utils/src/acl/identifier.rs b/core/tauri-utils/src/acl/identifier.rs index a5c4007229b6..5472ae5025cf 100644 --- a/core/tauri-utils/src/acl/identifier.rs +++ b/core/tauri-utils/src/acl/identifier.rs @@ -1,4 +1,6 @@ -use serde::{Deserialize, Deserializer}; +//! Identifier for plugins. + +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::num::NonZeroU8; use thiserror::Error; @@ -10,6 +12,7 @@ const MAX_LEN_PREFIX: usize = 64 - PLUGIN_PREFIX.len(); const MAX_LEN_BASE: usize = 64; const MAX_LEN_IDENTIFIER: usize = MAX_LEN_PREFIX + 1 + MAX_LEN_BASE; +/// Plugin identifier. #[derive(Debug)] pub struct Identifier { inner: String, @@ -24,11 +27,13 @@ impl AsRef for Identifier { } impl Identifier { + /// Get the identifier str. #[inline(always)] pub fn get(&self) -> &str { self.as_ref() } + /// Get the identifier without prefix. pub fn get_base(&self) -> &str { match self.separator_index() { None => self.get(), @@ -36,14 +41,17 @@ impl Identifier { } } + /// Get the prefix of the identifier. pub fn get_prefix(&self) -> Option<&str> { self.separator_index().map(|i| &self.inner[0..i]) } + /// Set the identifier prefix. pub fn set_prefix(&mut self) -> Result<(), ParseIdentifierError> { todo!() } + /// Get the identifier string and its separator. pub fn into_inner(self) -> (String, Option) { (self.inner, self.separator) } @@ -81,29 +89,37 @@ impl ValidByte { } } +/// Errors that can happen when parsing an identifier. #[derive(Debug, Error)] pub enum ParseIdentifierError { + /// Identifier start with the plugin prefix. #[error("identifiers cannot start with {}", PLUGIN_PREFIX)] StartsWithTauriPlugin, + /// Identifier empty. #[error("identifiers cannot be empty")] Empty, + /// Identifier is too long. #[error("identifiers cannot be longer than {}, found {0}", MAX_LEN_IDENTIFIER)] Humungous(usize), + /// Identifier is not in a valid format. #[error("identifiers can only include lowercase ASCII, hyphens which are not leading or trailing, and a single colon if using a prefix")] InvalidFormat, + /// Identifier has multiple separators. #[error( "identifiers can only include a single separator '{}'", IDENTIFIER_SEPARATOR )] MultipleSeparators, + /// Identifier has a trailing hyphen. #[error("identifiers cannot have a trailing hyphen")] TrailingHyphen, + /// Identifier has a prefix without a base. #[error("identifiers cannot have a prefix without a base")] PrefixWithoutBase, } @@ -176,6 +192,15 @@ impl<'de> Deserialize<'de> for Identifier { } } +impl Serialize for Identifier { + fn serialize(&self, serializer: S) -> std::result::Result + where + S: Serializer, + { + serializer.serialize_str(self.get()) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/core/tauri-utils/src/acl/mod.rs b/core/tauri-utils/src/acl/mod.rs index 6f3e1c7b1dd3..00f8e7c72e9e 100644 --- a/core/tauri-utils/src/acl/mod.rs +++ b/core/tauri-utils/src/acl/mod.rs @@ -12,7 +12,7 @@ pub mod value; /// Allowed and denied commands inside a permission. /// /// If two commands clash inside of `allow` and `deny`, it should be denied by default. -#[derive(Debug, Default, Deserialize)] +#[derive(Debug, Default, Serialize, Deserialize)] pub struct Commands { /// Allowed command. #[serde(default)] @@ -23,52 +23,67 @@ pub struct Commands { pub deny: Vec, } -#[derive(Debug, Default, Deserialize)] +/// A restriction of the command/endpoint functionality. +/// +/// 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, Serialize, Deserialize)] pub struct Scopes { - allow: Option, - deny: Option, + /// Data that defines what is allowed by the scope. + pub allow: Option, + /// Data that defines what is denied by the scope. + pub deny: Option, } -#[derive(Debug, Deserialize)] +/// Descriptions of explicit privileges of commands. +/// +/// It can enable commands to be accessible in the frontend of the application. +/// +/// If the scope is defined it can be used to fine grain control the access of individual or multiple commands. +#[derive(Debug, Serialize, Deserialize)] pub struct InlinedPermission { /// The version of the permission. - version: Option, + pub version: Option, /// A unique identifier for the permission. - identifier: Option, + pub identifier: String, /// Human-readable description of what the permission does. - description: Option, + pub description: Option, /// Allowed or denied commands when using this permission. #[serde(default)] - commands: Commands, + pub commands: Commands, /// Allowed or denied scoped when using this permission. #[serde(default)] - scopes: Scopes, + pub scopes: Scopes, } +/// Identifier of a permission #[derive(Debug, Clone, Serialize, Deserialize)] pub struct PermissionId { inner: String, } /// A permission. -#[derive(Debug, Deserialize)] +#[derive(Debug, Serialize, Deserialize)] pub struct Permission { + /// Permission data. #[serde(flatten)] - inner: InlinedPermission, + pub inner: InlinedPermission, } -#[derive(Debug, Deserialize)] +/// A set of direct permissions grouped together under a new name. +#[derive(Debug, Serialize, Deserialize)] pub struct PermissionSet { /// A unique identifier for the permission. - identifier: Identifier, + pub identifier: String, /// Human-readable description of what the permission does. - description: String, + pub description: String, /// All permissions this set contains. - permissions: Vec, + pub permissions: Vec, } diff --git a/core/tauri-utils/src/acl/plugin.rs b/core/tauri-utils/src/acl/plugin.rs index 8b137891791f..ce426c826240 100644 --- a/core/tauri-utils/src/acl/plugin.rs +++ b/core/tauri-utils/src/acl/plugin.rs @@ -1 +1,15 @@ +use std::collections::HashMap; +use super::{Permission, PermissionSet}; +use serde::Serialize; + +/// Plugin manifest. +#[derive(Serialize)] +pub struct Manifest { + /// Default permission. + pub default_permission: Option, + /// Plugin permissions. + pub permissions: HashMap, + /// Plugin permission sets. + pub permission_sets: HashMap, +} diff --git a/examples/api/src-tauri/Cargo.lock b/examples/api/src-tauri/Cargo.lock index 6067f2a8f5a1..85e50309428b 100644 --- a/examples/api/src-tauri/Cargo.lock +++ b/examples/api/src-tauri/Cargo.lock @@ -298,7 +298,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -333,7 +333,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -511,6 +511,38 @@ dependencies = [ "system-deps", ] +[[package]] +name = "camino" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ceed8ef69d8518a5dda55c07425450b58a4e1946f4951eab6d7191ee86c2443d" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "cargo_toml" version = "0.17.0" @@ -804,7 +836,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -814,7 +846,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37e366bff8cd32dd8754b0991fb66b279dc48f598c3a18914852a6673deef583" dependencies = [ "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -847,7 +879,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -858,7 +890,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -999,7 +1031,7 @@ checksum = "f95e2801cd355d4a1a3e3953ce6ee5ae9603a5c833455343a8bfe3f44d418246" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -1113,7 +1145,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -1206,7 +1238,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -1473,7 +1505,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -1552,7 +1584,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -2054,6 +2086,12 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + [[package]] name = "memchr" version = "2.6.4" @@ -2476,7 +2514,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -2664,9 +2702,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" dependencies = [ "unicode-ident", ] @@ -2682,9 +2720,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -2992,25 +3030,28 @@ name = "semver" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +dependencies = [ + "serde", +] [[package]] name = "serde" -version = "1.0.189" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" +checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.189" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" +checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -3032,7 +3073,7 @@ checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -3082,7 +3123,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -3313,9 +3354,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.38" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", @@ -3447,6 +3488,7 @@ dependencies = [ "serde_repr", "serialize-to-javascript", "state", + "static_assertions", "swift-rs", "tauri-build", "tauri-macros", @@ -3480,6 +3522,7 @@ dependencies = [ "serde_json", "swift-rs", "tauri-codegen", + "tauri-plugin", "tauri-utils", "tauri-winres", "walkdir", @@ -3516,11 +3559,24 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", "tauri-codegen", "tauri-utils", ] +[[package]] +name = "tauri-plugin" +version = "0.1.0" +dependencies = [ + "cargo_metadata", + "glob", + "serde", + "serde_json", + "tauri-utils", + "thiserror", + "toml 0.8.2", +] + [[package]] name = "tauri-plugin-cli" version = "2.0.0-alpha.3" @@ -3542,6 +3598,7 @@ dependencies = [ "serde", "tauri", "tauri-build", + "tauri-plugin", "thiserror", ] @@ -3596,6 +3653,7 @@ dependencies = [ "json-patch", "kuchikiki", "log", + "matchit", "memchr", "phf 0.11.2", "proc-macro2", @@ -3606,6 +3664,7 @@ dependencies = [ "serde_with", "serialize-to-javascript", "thiserror", + "toml 0.8.2", "url", "walkdir", ] @@ -3667,7 +3726,7 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -3851,7 +3910,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -4110,7 +4169,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", "wasm-bindgen-shared", ] @@ -4144,7 +4203,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4244,7 +4303,7 @@ checksum = "ac1345798ecd8122468840bcdf1b95e5dc6d2206c5e4b0eafa078d061f59c9bc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -4360,7 +4419,7 @@ checksum = "12168c33176773b86799be25e2a2ba07c7aab9968b37541f1094dbd7a60c8946" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -4371,7 +4430,7 @@ checksum = "9d8dc32e0095a7eeccebd0e3f09e9509365ecb3fc6ac4d6f5f14a3f6392942d1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] diff --git a/examples/api/src-tauri/tauri-plugin-sample/Cargo.toml b/examples/api/src-tauri/tauri-plugin-sample/Cargo.toml index 41c002a1a098..4d3131b6aba0 100644 --- a/examples/api/src-tauri/tauri-plugin-sample/Cargo.toml +++ b/examples/api/src-tauri/tauri-plugin-sample/Cargo.toml @@ -12,3 +12,4 @@ thiserror = "1" [build-dependencies] tauri-build = { path = "../../../../core/tauri-build/" } +tauri-plugin = { path = "../../../../core/tauri-plugin", features = ["build"] } diff --git a/examples/api/src-tauri/tauri-plugin-sample/build.rs b/examples/api/src-tauri/tauri-plugin-sample/build.rs index 35bb9b5a57cc..d62b8d414128 100644 --- a/examples/api/src-tauri/tauri-plugin-sample/build.rs +++ b/examples/api/src-tauri/tauri-plugin-sample/build.rs @@ -13,4 +13,6 @@ fn main() { println!("{error:#}"); exit(1); } + + tauri_plugin::build("./permissions/**/*.toml"); } diff --git a/examples/api/src-tauri/tauri-plugin-sample/permissions/ping.toml b/examples/api/src-tauri/tauri-plugin-sample/permissions/ping.toml new file mode 100644 index 000000000000..dbddd0cac1da --- /dev/null +++ b/examples/api/src-tauri/tauri-plugin-sample/permissions/ping.toml @@ -0,0 +1,5 @@ +[[permission]] +version = 1 +identifier = "allow-ping" +description = "This allows using the ping command." +commands.allow = ["ping"] diff --git a/examples/plugins/tauri-plugin-example/Cargo.toml b/examples/plugins/tauri-plugin-example/Cargo.toml index 6181b3d0f237..334b8070f521 100644 --- a/examples/plugins/tauri-plugin-example/Cargo.toml +++ b/examples/plugins/tauri-plugin-example/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" links = "tauri-plugin-example" [build-dependencies] -tauri-plugin = {path = "../../../core/tauri-plugin", features = ["build"]} +tauri-plugin = { path = "../../../core/tauri-plugin", features = ["build"] } [dependencies] tauri-plugin = { path = "../../../core/tauri-plugin" } diff --git a/examples/plugins/tauri-plugin-example/permissions/home-config.toml b/examples/plugins/tauri-plugin-example/permissions/home-config.toml index 4fc4a7d1a974..3d1bbf4dc89c 100644 --- a/examples/plugins/tauri-plugin-example/permissions/home-config.toml +++ b/examples/plugins/tauri-plugin-example/permissions/home-config.toml @@ -1,3 +1,4 @@ +[[permission]] version = 1 identifier = "deny-home-dir-config" description = "This denies read access to the complete $HOME folder." diff --git a/examples/plugins/tauri-plugin-example/permissions/home-dir.toml b/examples/plugins/tauri-plugin-example/permissions/home-dir.toml index a3641f838dd2..2b3dc1992501 100644 --- a/examples/plugins/tauri-plugin-example/permissions/home-dir.toml +++ b/examples/plugins/tauri-plugin-example/permissions/home-dir.toml @@ -1,3 +1,4 @@ +[[permission]] version = 1 identifier = "allow-home-dir" description = "This allows read access to the complete $HOME folder." From ce1fa7dd88f8d1047b602302ca6e58a856c95603 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Sun, 7 Jan 2024 16:22:21 -0300 Subject: [PATCH 12/69] parse capabilities [skip ci] --- core/tauri-build/Cargo.toml | 2 + core/tauri-build/src/acl.rs | 43 +++++++++++++- core/tauri-build/src/lib.rs | 57 +++++++++++++++++++ core/tauri-plugin/src/build/acl.rs | 4 ++ core/tauri-utils/src/acl/capability.rs | 28 +++------ core/tauri-utils/src/acl/identifier.rs | 2 +- core/tauri-utils/src/acl/mod.rs | 6 -- examples/api/src-tauri/Cargo.lock | 2 + .../api/src-tauri/capabilities/run-app.toml | 4 ++ 9 files changed, 120 insertions(+), 28 deletions(-) create mode 100644 examples/api/src-tauri/capabilities/run-app.toml diff --git a/core/tauri-build/Cargo.toml b/core/tauri-build/Cargo.toml index 933172c6bb64..c6b84c921e21 100644 --- a/core/tauri-build/Cargo.toml +++ b/core/tauri-build/Cargo.toml @@ -40,6 +40,8 @@ walkdir = "2" tauri-winres = "0.1" semver = "1" dirs-next = "2" +glob = "0.3" +toml = "0.8" [target."cfg(target_os = \"macos\")".dependencies] swift-rs = { version = "1.0.6", features = [ "build" ] } diff --git a/core/tauri-build/src/acl.rs b/core/tauri-build/src/acl.rs index e5448b026665..91b22e38b06b 100644 --- a/core/tauri-build/src/acl.rs +++ b/core/tauri-build/src/acl.rs @@ -1,9 +1,48 @@ use std::collections::HashMap; use anyhow::{Context, Result}; -use tauri_utils::acl::{plugin::Manifest, InlinedPermission, Permission, PermissionSet}; +use serde::Deserialize; +use tauri_utils::acl::{ + capability::Capability, plugin::Manifest, InlinedPermission, Permission, PermissionSet, +}; -pub fn process() -> Result> { +#[derive(Deserialize)] +#[serde(untagged)] +enum CapabilityFile { + Capability(Capability), + List { capabilities: Vec }, +} + +pub fn parse_capabilities(capabilities_path_pattern: &str) -> Result> { + let mut capabilities_map = HashMap::new(); + + for path in glob::glob(capabilities_path_pattern)?.flatten() { + println!("cargo:rerun-if-changed={}", path.display()); + + let capability_file = std::fs::read_to_string(&path)?; + let ext = path.extension().unwrap().to_string_lossy().to_string(); + let capability: CapabilityFile = match ext.as_str() { + "toml" => toml::from_str(&capability_file)?, + "json" => serde_json::from_str(&capability_file)?, + _ => return Err(anyhow::anyhow!("unknown capability format")), + }; + + match capability { + CapabilityFile::Capability(capability) => { + capabilities_map.insert(capability.identifier.clone(), capability); + } + CapabilityFile::List { capabilities } => { + for capability in capabilities { + capabilities_map.insert(capability.identifier.clone(), capability); + } + } + } + } + + Ok(capabilities_map) +} + +pub(crate) fn process() -> Result> { let permission_map = tauri_plugin::acl::read_permissions().context("failed to read plugin permissions")?; diff --git a/core/tauri-build/src/lib.rs b/core/tauri-build/src/lib.rs index 8d91861f6c8b..5309ddb7ca6f 100644 --- a/core/tauri-build/src/lib.rs +++ b/core/tauri-build/src/lib.rs @@ -42,6 +42,7 @@ mod static_vcruntime; pub use codegen::context::CodegenContext; const ACL_FILE_NAME: &str = "acl.json"; +const CAPABILITIES_FILE_NAME: &str = "capabilities.json"; fn copy_file(from: impl AsRef, to: impl AsRef) -> Result<()> { let from = from.as_ref(); @@ -336,6 +337,7 @@ impl WindowsAttributes { pub struct Attributes { #[allow(dead_code)] windows_attributes: WindowsAttributes, + capabilities_path_pattern: Option<&'static str>, } impl Attributes { @@ -350,6 +352,13 @@ impl Attributes { self.windows_attributes = windows_attributes; self } + + /// Set the glob pattern to be used to find the capabilities. + #[must_use] + pub fn capabilities_path_pattern(mut self, pattern: &'static str) -> Self { + self.capabilities_path_pattern.replace(pattern); + self + } } /// Run all build time helpers for your Tauri Application. @@ -449,6 +458,54 @@ pub fn try_build(attributes: Attributes) -> Result<()> { allowlist::check(&config, &mut manifest)?; let acl = acl::process()?; std::fs::write(out_dir.join(ACL_FILE_NAME), serde_json::to_string(&acl)?)?; + let capabilities = if let Some(pattern) = attributes.capabilities_path_pattern { + acl::parse_capabilities(pattern)? + } else { + acl::parse_capabilities("./capabilities/**/*")? + }; + + for capability in capabilities.values() { + for permission in &capability.permissions { + if let Some((plugin_name, permission_name)) = permission.get().split_once(':') { + let permission_exists = acl + .get(plugin_name) + .map(|manifest| { + if permission_name == "default" { + manifest.default_permission.is_some() + } else { + manifest.permissions.contains_key(permission_name) + || manifest.permission_sets.contains_key(permission_name) + } + }) + .unwrap_or(false); + + if !permission_exists { + let mut available_permissions = Vec::new(); + for (plugin, manifest) in &acl { + if manifest.default_permission.is_some() { + available_permissions.push(format!("{plugin}:default")); + } + for p in manifest.permissions.keys() { + available_permissions.push(format!("{plugin}:{p}")); + } + for p in manifest.permission_sets.keys() { + available_permissions.push(format!("{plugin}:{p}")); + } + } + + anyhow::bail!( + "Permission {} not found, expected one of {}", + permission.get(), + available_permissions.join(", ") + ); + } + } + } + } + std::fs::write( + out_dir.join(CAPABILITIES_FILE_NAME), + serde_json::to_string(&capabilities)?, + )?; let target_triple = std::env::var("TARGET").unwrap(); diff --git a/core/tauri-plugin/src/build/acl.rs b/core/tauri-plugin/src/build/acl.rs index 1994fbad6362..5fc66f237f00 100644 --- a/core/tauri-plugin/src/build/acl.rs +++ b/core/tauri-plugin/src/build/acl.rs @@ -49,6 +49,10 @@ pub fn define_permissions(pattern: &str) -> Result<(), Error> { .flatten() .collect::>(); + for path in &permission_files { + println!("cargo:rerun-if-changed={}", path.display()); + } + let permission_files_path = std::env::temp_dir().join(format!( "{}-permission-files", std::env::var("CARGO_PKG_NAME").unwrap() diff --git a/core/tauri-utils/src/acl/capability.rs b/core/tauri-utils/src/acl/capability.rs index 4b0e92f89300..d8e1e19a90aa 100644 --- a/core/tauri-utils/src/acl/capability.rs +++ b/core/tauri-utils/src/acl/capability.rs @@ -1,14 +1,8 @@ //! End-user abstraction for selecting permissions a window has access to. -use crate::acl::PermissionId; +use crate::acl::Identifier; use serde::{Deserialize, Serialize}; -/// Identifier of a capability. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct CapabilityId { - inner: String, -} - #[derive(Debug, Clone, Serialize, Deserialize)] /// A set of direct capabilities grouped together under a new name. @@ -24,18 +18,20 @@ pub struct CapabilitySet { /// Windows can be added to a capability by exact name or glob patterns like *, admin-* or main-window. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Capability { - identifier: CapabilityId, - description: String, + pub identifier: String, + #[serde(default)] + pub description: String, #[serde(default)] - context: CapabilityContext, - windows: Vec, - permissions: Vec, + pub context: CapabilityContext, + pub windows: Vec, + pub permissions: Vec, } /// Context of the capability. -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Default, Clone, Serialize, Deserialize)] pub enum CapabilityContext { /// Capability refers to local URL usage. + #[default] Local, /// Capability refers to remote usage. Remote { @@ -43,9 +39,3 @@ pub enum CapabilityContext { dangerous_remote: Vec, }, } - -impl Default for CapabilityContext { - fn default() -> Self { - Self::Local - } -} diff --git a/core/tauri-utils/src/acl/identifier.rs b/core/tauri-utils/src/acl/identifier.rs index 5472ae5025cf..e882b4a8500a 100644 --- a/core/tauri-utils/src/acl/identifier.rs +++ b/core/tauri-utils/src/acl/identifier.rs @@ -13,7 +13,7 @@ const MAX_LEN_BASE: usize = 64; const MAX_LEN_IDENTIFIER: usize = MAX_LEN_PREFIX + 1 + MAX_LEN_BASE; /// Plugin identifier. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Identifier { inner: String, separator: Option, diff --git a/core/tauri-utils/src/acl/mod.rs b/core/tauri-utils/src/acl/mod.rs index 00f8e7c72e9e..37e3772e7e72 100644 --- a/core/tauri-utils/src/acl/mod.rs +++ b/core/tauri-utils/src/acl/mod.rs @@ -61,12 +61,6 @@ pub struct InlinedPermission { pub scopes: Scopes, } -/// Identifier of a permission -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct PermissionId { - inner: String, -} - /// A permission. #[derive(Debug, Serialize, Deserialize)] pub struct Permission { diff --git a/examples/api/src-tauri/Cargo.lock b/examples/api/src-tauri/Cargo.lock index 85e50309428b..7bd60aa273ee 100644 --- a/examples/api/src-tauri/Cargo.lock +++ b/examples/api/src-tauri/Cargo.lock @@ -3513,6 +3513,7 @@ dependencies = [ "anyhow", "cargo_toml", "dirs-next", + "glob", "heck", "json-patch", "plist", @@ -3525,6 +3526,7 @@ dependencies = [ "tauri-plugin", "tauri-utils", "tauri-winres", + "toml 0.8.2", "walkdir", ] diff --git a/examples/api/src-tauri/capabilities/run-app.toml b/examples/api/src-tauri/capabilities/run-app.toml new file mode 100644 index 000000000000..0a80917c748d --- /dev/null +++ b/examples/api/src-tauri/capabilities/run-app.toml @@ -0,0 +1,4 @@ +identifier = "run-app" +description = "app capability" +windows = ["main"] +permissions = ["sample:allow-ping"] From ceeb4158b1d7dea34fb6f72fd817d9fa2fef52d2 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Thu, 11 Jan 2024 10:26:21 -0300 Subject: [PATCH 13/69] resolve acl (untested) [skip ci] --- core/tauri-codegen/src/context.rs | 171 ++++++++++++++++++++++++ core/tauri-utils/Cargo.toml | 1 - core/tauri-utils/src/acl/capability.rs | 2 +- core/tauri-utils/src/acl/identifier.rs | 4 +- core/tauri-utils/src/acl/mod.rs | 2 +- core/tauri-utils/src/acl/plugin.rs | 4 +- core/tauri-utils/src/acl/resolved.rs | 176 ++++++++++++++++++++----- core/tauri-utils/src/config.rs | 144 +------------------- core/tauri-utils/src/lib.rs | 2 + core/tauri-utils/src/tokens.rs | 141 ++++++++++++++++++++ core/tauri/src/lib.rs | 4 + examples/api/src-tauri/Cargo.lock | 7 - 12 files changed, 473 insertions(+), 185 deletions(-) create mode 100644 core/tauri-utils/src/tokens.rs diff --git a/core/tauri-codegen/src/context.rs b/core/tauri-codegen/src/context.rs index de448b071800..dbbb41acb1a9 100644 --- a/core/tauri-codegen/src/context.rs +++ b/core/tauri-codegen/src/context.rs @@ -2,6 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT +use std::collections::hash_map::DefaultHasher; +use std::collections::{BTreeMap, HashMap}; +use std::hash::{Hash, Hasher}; use std::path::{Path, PathBuf}; use std::{ffi::OsStr, str::FromStr}; @@ -10,6 +13,9 @@ use proc_macro2::TokenStream; use quote::quote; use sha2::{Digest, Sha256}; +use tauri_utils::acl::capability::Capability; +use tauri_utils::acl::plugin::Manifest; +use tauri_utils::acl::resolved::{CommandKey, Resolved, ResolvedCommand, ResolvedScope}; use tauri_utils::assets::AssetKey; use tauri_utils::config::{AppUrl, Config, PatternKind, WindowUrl}; use tauri_utils::html::{ @@ -19,6 +25,9 @@ use tauri_utils::platform::Target; use crate::embedded_assets::{AssetOptions, CspHashes, EmbeddedAssets, EmbeddedAssetsError}; +const ACL_FILE_NAME: &str = "acl.json"; +const CAPABILITIES_FILE_NAME: &str = "capabilities.json"; + /// Necessary data needed by [`context_codegen`] to generate code for a Tauri application context. pub struct ContextData { pub dev: bool, @@ -373,6 +382,8 @@ pub fn context_codegen(data: ContextData) -> Result Result Result> { + let acl_file = std::fs::read_to_string(out_dir.join(ACL_FILE_NAME))?; + let acl: HashMap = serde_json::from_str(&acl_file)?; + + let capabilities_file = std::fs::read_to_string(out_dir.join(CAPABILITIES_FILE_NAME))?; + let capabilities: HashMap = serde_json::from_str(&capabilities_file)?; + + #[derive(Debug, Default)] + struct ResolvedCommandTemp { + pub windows: Vec, + pub scope: Vec, + pub resolved_scope_key: usize, + } + + let mut allowed_commands = HashMap::new(); + let mut denied_commands = HashMap::new(); + + let mut current_scope_id = 0; + let mut scopes = HashMap::new(); + + // resolve commands + for capability in capabilities.values() { + for permission_id in &capability.permissions { + let permission_name = permission_id.get_base(); + + if let Some(plugin_name) = permission_id.get_prefix() { + let manifest = acl.get(plugin_name).ok_or_else(|| { + format!( + "unknown plugin {plugin_name}, expected one of {:?}", + acl.keys().cloned().collect::>().join(", ") + ) + })?; + + let permissions = if permission_name == "default" { + vec![manifest + .default_permission + .as_ref() + .ok_or_else(|| format!("plugin {plugin_name} has no default permission"))?] + } else if let Some(set) = manifest.permission_sets.get(permission_name) { + let mut resolved = Vec::new(); + for p in &set.permissions { + resolved.push( + manifest + .permissions + .get(p) + .ok_or_else(|| format!("permission {p} in set {permission_name} not found"))?, + ); + } + resolved + } else if let Some(permission) = manifest.permissions.get(permission_name) { + vec![permission] + } else { + return Err( + format!("unknown permission {permission_name} for plugin {plugin_name}").into(), + ); + }; + + fn resolve_command( + commands: &mut HashMap, + command: String, + capability: &Capability, + scope_id: usize, + ) { + let resolved = commands + .entry(CommandKey { + name: command, + context: capability.context.clone(), + }) + .or_insert_with(|| ResolvedCommandTemp::default()); + + resolved.windows.extend(capability.windows.clone()); + resolved.scope.push(scope_id); + } + + for permission in permissions { + current_scope_id += 1; + scopes.insert(current_scope_id, permission.inner.scopes.clone()); + + for allowed_command in &permission.inner.commands.allow { + resolve_command( + &mut allowed_commands, + format!("plugin:{plugin_name}|{allowed_command}"), + &capability, + current_scope_id, + ); + } + + for denied_command in &permission.inner.commands.deny { + resolve_command( + &mut denied_commands, + format!("plugin:{plugin_name}|{denied_command}"), + &capability, + current_scope_id, + ); + } + } + } + } + } + + // resolve scopes + let mut resolved_scopes = BTreeMap::new(); + + for allowed in allowed_commands.values_mut() { + allowed.scope.sort(); + + let mut hasher = DefaultHasher::new(); + allowed.scope.hash(&mut hasher); + let hash = hasher.finish() as usize; + + allowed.resolved_scope_key = hash; + + let resolved_scope = ResolvedScope { + allow: allowed + .scope + .iter() + .flat_map(|s| scopes.get(s).unwrap().allow.clone()) + .collect(), + deny: allowed + .scope + .iter() + .flat_map(|s| scopes.get(s).unwrap().deny.clone()) + .collect(), + }; + + resolved_scopes.insert(hash, resolved_scope); + } + + let resolved = Resolved { + allowed_commands: allowed_commands + .into_iter() + .map(|(key, cmd)| { + ( + key, + ResolvedCommand { + windows: cmd.windows, + scope: cmd.resolved_scope_key, + }, + ) + }) + .collect(), + denied_commands: denied_commands + .into_iter() + .map(|(key, cmd)| { + ( + key, + ResolvedCommand { + windows: cmd.windows, + scope: cmd.resolved_scope_key, + }, + ) + }) + .collect(), + scopes: resolved_scopes, + }; + + Ok(resolved) +} + fn ico_icon>( root: &TokenStream, out_dir: &Path, diff --git a/core/tauri-utils/Cargo.toml b/core/tauri-utils/Cargo.toml index e91d28a519ad..5e27063c068d 100644 --- a/core/tauri-utils/Cargo.toml +++ b/core/tauri-utils/Cargo.toml @@ -39,7 +39,6 @@ semver = "1" infer = "0.15" dunce = "1" log = "0.4.20" -matchit = "0.7" [target."cfg(target_os = \"linux\")".dependencies] heck = "0.4" diff --git a/core/tauri-utils/src/acl/capability.rs b/core/tauri-utils/src/acl/capability.rs index d8e1e19a90aa..ecc48a026ef3 100644 --- a/core/tauri-utils/src/acl/capability.rs +++ b/core/tauri-utils/src/acl/capability.rs @@ -28,7 +28,7 @@ pub struct Capability { } /// Context of the capability. -#[derive(Debug, Default, Clone, Serialize, Deserialize)] +#[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord, Hash)] pub enum CapabilityContext { /// Capability refers to local URL usage. #[default] diff --git a/core/tauri-utils/src/acl/identifier.rs b/core/tauri-utils/src/acl/identifier.rs index e882b4a8500a..5c9996a2c6b2 100644 --- a/core/tauri-utils/src/acl/identifier.rs +++ b/core/tauri-utils/src/acl/identifier.rs @@ -168,10 +168,10 @@ impl TryFrom for Identifier { match prev { // empty base - ValidByte::Separator => return Err(Self::Error::TrailingHyphen), + ValidByte::Separator => return Err(Self::Error::PrefixWithoutBase), // trailing hyphen - ValidByte::Byte(b'-') => return Err(Self::Error::PrefixWithoutBase), + ValidByte::Byte(b'-') => return Err(Self::Error::TrailingHyphen), _ => (), } diff --git a/core/tauri-utils/src/acl/mod.rs b/core/tauri-utils/src/acl/mod.rs index 37e3772e7e72..faa13d3f0fe3 100644 --- a/core/tauri-utils/src/acl/mod.rs +++ b/core/tauri-utils/src/acl/mod.rs @@ -28,7 +28,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, Serialize, Deserialize)] +#[derive(Debug, Default, Clone, Serialize, Deserialize)] pub struct Scopes { /// Data that defines what is allowed by the scope. pub allow: Option, diff --git a/core/tauri-utils/src/acl/plugin.rs b/core/tauri-utils/src/acl/plugin.rs index ce426c826240..8f69253fda46 100644 --- a/core/tauri-utils/src/acl/plugin.rs +++ b/core/tauri-utils/src/acl/plugin.rs @@ -1,10 +1,10 @@ use std::collections::HashMap; use super::{Permission, PermissionSet}; -use serde::Serialize; +use serde::{Deserialize, Serialize}; /// Plugin manifest. -#[derive(Serialize)] +#[derive(Serialize, Deserialize)] pub struct Manifest { /// Default permission. pub default_permission: Option, diff --git a/core/tauri-utils/src/acl/resolved.rs b/core/tauri-utils/src/acl/resolved.rs index 42ef296bc273..34c84fe387d9 100644 --- a/core/tauri-utils/src/acl/resolved.rs +++ b/core/tauri-utils/src/acl/resolved.rs @@ -1,45 +1,161 @@ -use matchit::Router; -use serde::de::DeserializeOwned; -use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; -/// TODO: the current proof of concept uses [`matchit`], but we should use a simplified -/// router router that __only__ supports static and wildcard values (without wildcard params) -pub struct WindowMatcher { - inner: Router, -} +use serde::{Deserialize, Serialize}; -pub struct WindowMatch { - inner: BTreeMap, -} +use super::{capability::CapabilityContext, Value}; -pub enum ResolvedCommand { - Deny, - Allow(ResolvedScopes), -} +pub type ScopeKey = usize; -pub enum ScopeKind<'de, T> -where - T: Serialize + Deserialize<'de>, -{ - Allow(&'de T), - Deny(&'de T), +pub struct ResolvedCommand { + pub windows: Vec, + pub scope: ScopeKey, } -pub struct ResolvedScopes +pub struct ResolvedScope where T: Serialize, for<'de> T: Deserialize<'de>, { - allow: Vec, - deny: Vec, + pub allow: Vec, + pub deny: Vec, } -impl ResolvedScopes -where - T: Serialize + DeserializeOwned, - for<'de> T: Deserialize<'de>, -{ +#[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +pub struct CommandKey { + pub name: String, + pub context: CapabilityContext, } -pub struct Resolved {} +pub struct Resolved { + pub allowed_commands: BTreeMap, + pub denied_commands: BTreeMap, + pub scopes: BTreeMap>, +} + +#[cfg(feature = "build")] +mod build { + use proc_macro2::TokenStream; + use quote::{quote, ToTokens, TokenStreamExt}; + use std::convert::identity; + + use super::*; + use crate::{acl::Number, tokens::*}; + + /// Write a `TokenStream` of the `$struct`'s fields to the `$tokens`. + /// + /// All fields must represent a binding of the same name that implements `ToTokens`. + macro_rules! literal_struct { + ($tokens:ident, $struct:ident, $($field:ident),+) => { + $tokens.append_all(quote! { + ::tauri::utils::acl::resolved::$struct { + $($field: #$field),+ + } + }) + }; + } + + 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::Local => { + quote! { #prefix::Local } + } + Self::Remote { dangerous_remote } => { + let dangerous_remote = vec_lit(dangerous_remote, str_lit); + quote! { #prefix::Remote { dangerous_remote } } + } + }); + } + } + + impl ToTokens for CommandKey { + fn to_tokens(&self, tokens: &mut TokenStream) { + let name = str_lit(&self.name); + let context = &self.context; + literal_struct!(tokens, CommandKey, name, context) + } + } + + impl ToTokens for ResolvedCommand { + fn to_tokens(&self, tokens: &mut TokenStream) { + let windows = vec_lit(&self.windows, str_lit); + let scope = self.scope; + literal_struct!(tokens, ResolvedCommand, windows, scope) + } + } + + impl ToTokens for Number { + fn to_tokens(&self, tokens: &mut TokenStream) { + let prefix = quote! { ::tauri::utils::acl:::Number }; + + tokens.append_all(match self { + Self::Int(i) => { + quote! { #prefix::Int(i) } + } + Self::Float(f) => { + quote! { #prefix::Float (f) } + } + }); + } + } + + impl ToTokens for Value { + fn to_tokens(&self, tokens: &mut TokenStream) { + let prefix = quote! { ::tauri::acl::Value }; + + tokens.append_all(match self { + Value::Bool(bool) => quote! { #prefix::Bool(#bool) }, + Value::Number(number) => quote! { #prefix::Number(#number) }, + Value::String(str) => { + let s = str_lit(str); + quote! { #prefix::String(#s) } + } + Value::List(vec) => { + let items = vec_lit(vec, identity); + quote! { #prefix::Array(#items) } + } + Value::Map(map) => { + let map = map_lit(quote! { ::tauri::acl::Map }, map, str_lit, identity); + quote! { #prefix::Map(#map) } + } + }); + } + } + + impl ToTokens for ResolvedScope { + fn to_tokens(&self, tokens: &mut TokenStream) { + let allow = vec_lit(&self.allow, identity); + let deny = vec_lit(&self.deny, identity); + literal_struct!(tokens, ResolvedScope, allow, deny) + } + } + + impl ToTokens for Resolved { + fn to_tokens(&self, tokens: &mut TokenStream) { + let allowed_commands = map_lit( + quote! { ::std::collections::BTreeMap }, + &self.allowed_commands, + identity, + identity, + ); + + let denied_commands = map_lit( + quote! { ::std::collections::BTreeMap }, + &self.denied_commands, + identity, + identity, + ); + + let scopes = map_lit( + quote! { ::std::collections::BTreeMap }, + &self.scopes, + identity, + identity, + ); + + literal_struct!(tokens, Resolved, allowed_commands, denied_commands, scopes) + } + } +} diff --git a/core/tauri-utils/src/config.rs b/core/tauri-utils/src/config.rs index 253cfa3d7bc5..5a5cb06ead1f 100644 --- a/core/tauri-utils/src/config.rs +++ b/core/tauri-utils/src/config.rs @@ -2140,149 +2140,11 @@ fn default_build() -> BuildConfig { /// application using tauri while only parsing it once (in the build script). #[cfg(feature = "build")] mod build { - use std::{convert::identity, path::Path}; - + use super::*; + use crate::tokens::*; use proc_macro2::TokenStream; use quote::{quote, ToTokens, TokenStreamExt}; - - use super::*; - - use serde_json::Value as JsonValue; - - /// Create a `String` constructor `TokenStream`. - /// - /// e.g. `"Hello World" -> String::from("Hello World"). - /// This takes a `&String` to reduce casting all the `&String` -> `&str` manually. - fn str_lit(s: impl AsRef) -> TokenStream { - let s = s.as_ref(); - quote! { #s.into() } - } - - /// Create an `Option` constructor `TokenStream`. - fn opt_lit(item: Option<&impl ToTokens>) -> TokenStream { - match item { - None => quote! { ::core::option::Option::None }, - Some(item) => quote! { ::core::option::Option::Some(#item) }, - } - } - - /// Helper function to combine an `opt_lit` with `str_lit`. - fn opt_str_lit(item: Option>) -> TokenStream { - opt_lit(item.map(str_lit).as_ref()) - } - - /// Helper function to combine an `opt_lit` with a list of `str_lit` - fn opt_vec_str_lit(item: Option>>) -> TokenStream { - opt_lit(item.map(|list| vec_lit(list, str_lit)).as_ref()) - } - - /// Create a `Vec` constructor, mapping items with a function that spits out `TokenStream`s. - fn vec_lit( - list: impl IntoIterator, - map: impl Fn(Raw) -> Tokens, - ) -> TokenStream - where - Tokens: ToTokens, - { - let items = list.into_iter().map(map); - quote! { vec![#(#items),*] } - } - - /// Create a `PathBuf` constructor `TokenStream`. - /// - /// e.g. `"Hello World" -> String::from("Hello World"). - fn path_buf_lit(s: impl AsRef) -> TokenStream { - let s = s.as_ref().to_string_lossy().into_owned(); - quote! { ::std::path::PathBuf::from(#s) } - } - - /// Creates a `Url` constructor `TokenStream`. - fn url_lit(url: &Url) -> TokenStream { - let url = url.as_str(); - quote! { #url.parse().unwrap() } - } - - /// Create a map constructor, mapping keys and values with other `TokenStream`s. - /// - /// This function is pretty generic because the types of keys AND values get transformed. - fn map_lit( - map_type: TokenStream, - map: Map, - map_key: FuncKey, - map_value: FuncValue, - ) -> TokenStream - where - ::IntoIter: ExactSizeIterator, - Map: IntoIterator, - TokenStreamKey: ToTokens, - TokenStreamValue: ToTokens, - FuncKey: Fn(Key) -> TokenStreamKey, - FuncValue: Fn(Value) -> TokenStreamValue, - { - let ident = quote::format_ident!("map"); - let map = map.into_iter(); - - if map.len() > 0 { - let items = map.map(|(key, value)| { - let key = map_key(key); - let value = map_value(value); - quote! { #ident.insert(#key, #value); } - }); - - quote! {{ - let mut #ident = #map_type::new(); - #(#items)* - #ident - }} - } else { - quote! { #map_type::new() } - } - } - - /// Create a `serde_json::Value` variant `TokenStream` for a number - fn json_value_number_lit(num: &serde_json::Number) -> TokenStream { - // See https://docs.rs/serde_json/1/serde_json/struct.Number.html for guarantees - let prefix = quote! { ::serde_json::Value }; - if num.is_u64() { - // guaranteed u64 - let num = num.as_u64().unwrap(); - quote! { #prefix::Number(#num.into()) } - } else if num.is_i64() { - // guaranteed i64 - let num = num.as_i64().unwrap(); - quote! { #prefix::Number(#num.into()) } - } else if num.is_f64() { - // guaranteed f64 - let num = num.as_f64().unwrap(); - quote! { #prefix::Number(::serde_json::Number::from_f64(#num).unwrap(/* safe to unwrap, guaranteed f64 */)) } - } else { - // invalid number - quote! { #prefix::Null } - } - } - - /// Create a `serde_json::Value` constructor `TokenStream` - fn json_value_lit(jv: &JsonValue) -> TokenStream { - let prefix = quote! { ::serde_json::Value }; - - match jv { - JsonValue::Null => quote! { #prefix::Null }, - JsonValue::Bool(bool) => quote! { #prefix::Bool(#bool) }, - JsonValue::Number(number) => json_value_number_lit(number), - JsonValue::String(str) => { - let s = str_lit(str); - quote! { #prefix::String(#s) } - } - JsonValue::Array(vec) => { - let items = vec.iter().map(json_value_lit); - quote! { #prefix::Array(vec![#(#items),*]) } - } - JsonValue::Object(map) => { - let map = map_lit(quote! { ::serde_json::Map }, map, str_lit, json_value_lit); - quote! { #prefix::Object(#map) } - } - } - } + use std::convert::identity; /// Write a `TokenStream` of the `$struct`'s fields to the `$tokens`. /// diff --git a/core/tauri-utils/src/lib.rs b/core/tauri-utils/src/lib.rs index 28416d9b5e78..18e742505dfb 100644 --- a/core/tauri-utils/src/lib.rs +++ b/core/tauri-utils/src/lib.rs @@ -34,6 +34,8 @@ pub mod platform; /// Prepare application resources and sidecars. #[cfg(feature = "resources")] pub mod resources; +#[cfg(feature = "build")] +pub mod tokens; /// Application pattern. pub mod pattern; diff --git a/core/tauri-utils/src/tokens.rs b/core/tauri-utils/src/tokens.rs new file mode 100644 index 000000000000..9a52498ab343 --- /dev/null +++ b/core/tauri-utils/src/tokens.rs @@ -0,0 +1,141 @@ +use std::path::Path; + +use proc_macro2::TokenStream; +use quote::{quote, ToTokens}; +use serde_json::Value as JsonValue; +use url::Url; + +/// Create a `String` constructor `TokenStream`. +/// +/// e.g. `"Hello World" -> String::from("Hello World"). +/// This takes a `&String` to reduce casting all the `&String` -> `&str` manually. +pub fn str_lit(s: impl AsRef) -> TokenStream { + let s = s.as_ref(); + quote! { #s.into() } +} + +/// Create an `Option` constructor `TokenStream`. +pub fn opt_lit(item: Option<&impl ToTokens>) -> TokenStream { + match item { + None => quote! { ::core::option::Option::None }, + Some(item) => quote! { ::core::option::Option::Some(#item) }, + } +} + +/// Helper function to combine an `opt_lit` with `str_lit`. +pub fn opt_str_lit(item: Option>) -> TokenStream { + opt_lit(item.map(str_lit).as_ref()) +} + +/// Helper function to combine an `opt_lit` with a list of `str_lit` +pub fn opt_vec_str_lit(item: Option>>) -> TokenStream { + opt_lit(item.map(|list| vec_lit(list, str_lit)).as_ref()) +} + +/// Create a `Vec` constructor, mapping items with a function that spits out `TokenStream`s. +pub fn vec_lit( + list: impl IntoIterator, + map: impl Fn(Raw) -> Tokens, +) -> TokenStream +where + Tokens: ToTokens, +{ + let items = list.into_iter().map(map); + quote! { vec![#(#items),*] } +} + +/// Create a `PathBuf` constructor `TokenStream`. +/// +/// e.g. `"Hello World" -> String::from("Hello World"). +pub fn path_buf_lit(s: impl AsRef) -> TokenStream { + let s = s.as_ref().to_string_lossy().into_owned(); + quote! { ::std::path::PathBuf::from(#s) } +} + +/// Creates a `Url` constructor `TokenStream`. +pub fn url_lit(url: &Url) -> TokenStream { + let url = url.as_str(); + quote! { #url.parse().unwrap() } +} + +/// Create a map constructor, mapping keys and values with other `TokenStream`s. +/// +/// This function is pretty generic because the types of keys AND values get transformed. +pub fn map_lit( + map_type: TokenStream, + map: Map, + map_key: FuncKey, + map_value: FuncValue, +) -> TokenStream +where + ::IntoIter: ExactSizeIterator, + Map: IntoIterator, + TokenStreamKey: ToTokens, + TokenStreamValue: ToTokens, + FuncKey: Fn(Key) -> TokenStreamKey, + FuncValue: Fn(Value) -> TokenStreamValue, +{ + let ident = quote::format_ident!("map"); + let map = map.into_iter(); + + if map.len() > 0 { + let items = map.map(|(key, value)| { + let key = map_key(key); + let value = map_value(value); + quote! { #ident.insert(#key, #value); } + }); + + quote! {{ + let mut #ident = #map_type::new(); + #(#items)* + #ident + }} + } else { + quote! { #map_type::new() } + } +} + +/// Create a `serde_json::Value` variant `TokenStream` for a number +pub fn json_value_number_lit(num: &serde_json::Number) -> TokenStream { + // See https://docs.rs/serde_json/1/serde_json/struct.Number.html for guarantees + let prefix = quote! { ::serde_json::Value }; + if num.is_u64() { + // guaranteed u64 + let num = num.as_u64().unwrap(); + quote! { #prefix::Number(#num.into()) } + } else if num.is_i64() { + // guaranteed i64 + let num = num.as_i64().unwrap(); + quote! { #prefix::Number(#num.into()) } + } else if num.is_f64() { + // guaranteed f64 + let num = num.as_f64().unwrap(); + quote! { #prefix::Number(::serde_json::Number::from_f64(#num).unwrap(/* safe to unwrap, guaranteed f64 */)) } + } else { + // invalid number + quote! { #prefix::Null } + } +} + +/// Create a `serde_json::Value` constructor `TokenStream` +pub fn json_value_lit(jv: &JsonValue) -> TokenStream { + let prefix = quote! { ::serde_json::Value }; + + match jv { + JsonValue::Null => quote! { #prefix::Null }, + JsonValue::Bool(bool) => quote! { #prefix::Bool(#bool) }, + JsonValue::Number(number) => json_value_number_lit(number), + JsonValue::String(str) => { + let s = str_lit(str); + quote! { #prefix::String(#s) } + } + JsonValue::Array(vec) => { + let items = vec.iter().map(json_value_lit); + quote! { #prefix::Array(vec![#(#items),*]) } + } + JsonValue::Object(map) => { + let map = map_lit(quote! { ::serde_json::Map }, map, str_lit, json_value_lit); + quote! { #prefix::Object(#map) } + } + } +} diff --git a/core/tauri/src/lib.rs b/core/tauri/src/lib.rs index a380b7411346..779d61950443 100644 --- a/core/tauri/src/lib.rs +++ b/core/tauri/src/lib.rs @@ -187,6 +187,7 @@ use std::{ fmt::{self, Debug}, sync::MutexGuard, }; +use utils::acl::resolved::Resolved; #[cfg(feature = "wry")] #[cfg_attr(docsrs, doc(cfg(feature = "wry")))] @@ -417,6 +418,7 @@ pub struct Context { pub(crate) package_info: PackageInfo, pub(crate) _info_plist: (), pub(crate) pattern: Pattern, + pub(crate) resolved_acl: Resolved, } impl fmt::Debug for Context { @@ -517,6 +519,7 @@ impl Context { package_info: PackageInfo, info_plist: (), pattern: Pattern, + resolved_acl: Resolved, ) -> Self { Self { config, @@ -528,6 +531,7 @@ impl Context { package_info, _info_plist: info_plist, pattern, + resolved_acl, } } diff --git a/examples/api/src-tauri/Cargo.lock b/examples/api/src-tauri/Cargo.lock index 7bd60aa273ee..d13e5cac3b3e 100644 --- a/examples/api/src-tauri/Cargo.lock +++ b/examples/api/src-tauri/Cargo.lock @@ -2086,12 +2086,6 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" -[[package]] -name = "matchit" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" - [[package]] name = "memchr" version = "2.6.4" @@ -3655,7 +3649,6 @@ dependencies = [ "json-patch", "kuchikiki", "log", - "matchit", "memchr", "phf 0.11.2", "proc-macro2", From 5a889213c03bd8bec7fc31fbdbe39ea9f7e26bba Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Thu, 11 Jan 2024 12:50:23 -0300 Subject: [PATCH 14/69] split functionality, add some docs --- core/tauri-build/src/acl.rs | 48 ++++- core/tauri-build/src/lib.rs | 47 +---- core/tauri-codegen/src/context.rs | 180 ++---------------- core/tauri-codegen/src/context/resolve_acl.rs | 178 +++++++++++++++++ core/tauri-utils/src/acl/capability.rs | 7 + core/tauri-utils/src/acl/mod.rs | 6 + core/tauri-utils/src/acl/plugin.rs | 2 + core/tauri-utils/src/acl/resolved.rs | 19 +- core/tauri-utils/src/acl/value.rs | 3 + tooling/cli/Cargo.lock | 1 - 10 files changed, 283 insertions(+), 208 deletions(-) create mode 100644 core/tauri-codegen/src/context/resolve_acl.rs diff --git a/core/tauri-build/src/acl.rs b/core/tauri-build/src/acl.rs index 91b22e38b06b..e761d7e9c75c 100644 --- a/core/tauri-build/src/acl.rs +++ b/core/tauri-build/src/acl.rs @@ -42,7 +42,7 @@ pub fn parse_capabilities(capabilities_path_pattern: &str) -> Result Result> { +pub(crate) fn get_plugin_manifests() -> Result> { let permission_map = tauri_plugin::acl::read_permissions().context("failed to read plugin permissions")?; @@ -99,3 +99,49 @@ pub(crate) fn process() -> Result> { Ok(processed) } + +pub(crate) fn validate_capabilities( + plugin_manifests: &HashMap, + capabilities: &HashMap, +) -> Result<()> { + for capability in capabilities.values() { + for permission in &capability.permissions { + if let Some((plugin_name, permission_name)) = permission.get().split_once(':') { + let permission_exists = plugin_manifests + .get(plugin_name) + .map(|manifest| { + if permission_name == "default" { + manifest.default_permission.is_some() + } else { + manifest.permissions.contains_key(permission_name) + || manifest.permission_sets.contains_key(permission_name) + } + }) + .unwrap_or(false); + + if !permission_exists { + let mut available_permissions = Vec::new(); + for (plugin, manifest) in plugin_manifests { + if manifest.default_permission.is_some() { + available_permissions.push(format!("{plugin}:default")); + } + for p in manifest.permissions.keys() { + available_permissions.push(format!("{plugin}:{p}")); + } + for p in manifest.permission_sets.keys() { + available_permissions.push(format!("{plugin}:{p}")); + } + } + + anyhow::bail!( + "Permission {} not found, expected one of {}", + permission.get(), + available_permissions.join(", ") + ); + } + } + } + } + + Ok(()) +} diff --git a/core/tauri-build/src/lib.rs b/core/tauri-build/src/lib.rs index 5309ddb7ca6f..581babb92851 100644 --- a/core/tauri-build/src/lib.rs +++ b/core/tauri-build/src/lib.rs @@ -41,7 +41,7 @@ mod static_vcruntime; #[cfg_attr(docsrs, doc(cfg(feature = "codegen")))] pub use codegen::context::CodegenContext; -const ACL_FILE_NAME: &str = "acl.json"; +const PLUGIN_MANIFESTS_FILE_NAME: &str = "plugin-manifests.json"; const CAPABILITIES_FILE_NAME: &str = "capabilities.json"; fn copy_file(from: impl AsRef, to: impl AsRef) -> Result<()> { @@ -456,52 +456,19 @@ pub fn try_build(attributes: Attributes) -> Result<()> { let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap()); allowlist::check(&config, &mut manifest)?; - let acl = acl::process()?; - std::fs::write(out_dir.join(ACL_FILE_NAME), serde_json::to_string(&acl)?)?; + let plugin_manifests = acl::get_plugin_manifests()?; + std::fs::write( + out_dir.join(PLUGIN_MANIFESTS_FILE_NAME), + serde_json::to_string(&plugin_manifests)?, + )?; let capabilities = if let Some(pattern) = attributes.capabilities_path_pattern { acl::parse_capabilities(pattern)? } else { acl::parse_capabilities("./capabilities/**/*")? }; - for capability in capabilities.values() { - for permission in &capability.permissions { - if let Some((plugin_name, permission_name)) = permission.get().split_once(':') { - let permission_exists = acl - .get(plugin_name) - .map(|manifest| { - if permission_name == "default" { - manifest.default_permission.is_some() - } else { - manifest.permissions.contains_key(permission_name) - || manifest.permission_sets.contains_key(permission_name) - } - }) - .unwrap_or(false); - - if !permission_exists { - let mut available_permissions = Vec::new(); - for (plugin, manifest) in &acl { - if manifest.default_permission.is_some() { - available_permissions.push(format!("{plugin}:default")); - } - for p in manifest.permissions.keys() { - available_permissions.push(format!("{plugin}:{p}")); - } - for p in manifest.permission_sets.keys() { - available_permissions.push(format!("{plugin}:{p}")); - } - } + acl::validate_capabilities(&plugin_manifests, &capabilities)?; - anyhow::bail!( - "Permission {} not found, expected one of {}", - permission.get(), - available_permissions.join(", ") - ); - } - } - } - } std::fs::write( out_dir.join(CAPABILITIES_FILE_NAME), serde_json::to_string(&capabilities)?, diff --git a/core/tauri-codegen/src/context.rs b/core/tauri-codegen/src/context.rs index dbbb41acb1a9..41e618562967 100644 --- a/core/tauri-codegen/src/context.rs +++ b/core/tauri-codegen/src/context.rs @@ -2,9 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -use std::collections::hash_map::DefaultHasher; -use std::collections::{BTreeMap, HashMap}; -use std::hash::{Hash, Hasher}; +use std::collections::HashMap; use std::path::{Path, PathBuf}; use std::{ffi::OsStr, str::FromStr}; @@ -15,7 +13,6 @@ use sha2::{Digest, Sha256}; use tauri_utils::acl::capability::Capability; use tauri_utils::acl::plugin::Manifest; -use tauri_utils::acl::resolved::{CommandKey, Resolved, ResolvedCommand, ResolvedScope}; use tauri_utils::assets::AssetKey; use tauri_utils::config::{AppUrl, Config, PatternKind, WindowUrl}; use tauri_utils::html::{ @@ -25,7 +22,9 @@ use tauri_utils::platform::Target; use crate::embedded_assets::{AssetOptions, CspHashes, EmbeddedAssets, EmbeddedAssetsError}; -const ACL_FILE_NAME: &str = "acl.json"; +mod resolve_acl; + +const PLUGIN_MANIFESTS_FILE_NAME: &str = "plugin-manifests.json"; const CAPABILITIES_FILE_NAME: &str = "capabilities.json"; /// Necessary data needed by [`context_codegen`] to generate code for a Tauri application context. @@ -382,7 +381,17 @@ pub fn context_codegen(data: ContextData) -> Result = + serde_json::from_str(&acl_file).expect("failed to parse plugin manifest map"); + + let capabilities_file = std::fs::read_to_string(out_dir.join(CAPABILITIES_FILE_NAME)) + .expect("failed to read capabilities"); + let capabilities: HashMap = + serde_json::from_str(&capabilities_file).expect("failed to parse capabilities"); + + let resolved_act = resolve_acl::resolve(acl, capabilities).expect("failed to resolve ACL"); Ok(quote!({ #[allow(unused_mut, clippy::let_and_return)] @@ -401,165 +410,6 @@ pub fn context_codegen(data: ContextData) -> Result Result> { - let acl_file = std::fs::read_to_string(out_dir.join(ACL_FILE_NAME))?; - let acl: HashMap = serde_json::from_str(&acl_file)?; - - let capabilities_file = std::fs::read_to_string(out_dir.join(CAPABILITIES_FILE_NAME))?; - let capabilities: HashMap = serde_json::from_str(&capabilities_file)?; - - #[derive(Debug, Default)] - struct ResolvedCommandTemp { - pub windows: Vec, - pub scope: Vec, - pub resolved_scope_key: usize, - } - - let mut allowed_commands = HashMap::new(); - let mut denied_commands = HashMap::new(); - - let mut current_scope_id = 0; - let mut scopes = HashMap::new(); - - // resolve commands - for capability in capabilities.values() { - for permission_id in &capability.permissions { - let permission_name = permission_id.get_base(); - - if let Some(plugin_name) = permission_id.get_prefix() { - let manifest = acl.get(plugin_name).ok_or_else(|| { - format!( - "unknown plugin {plugin_name}, expected one of {:?}", - acl.keys().cloned().collect::>().join(", ") - ) - })?; - - let permissions = if permission_name == "default" { - vec![manifest - .default_permission - .as_ref() - .ok_or_else(|| format!("plugin {plugin_name} has no default permission"))?] - } else if let Some(set) = manifest.permission_sets.get(permission_name) { - let mut resolved = Vec::new(); - for p in &set.permissions { - resolved.push( - manifest - .permissions - .get(p) - .ok_or_else(|| format!("permission {p} in set {permission_name} not found"))?, - ); - } - resolved - } else if let Some(permission) = manifest.permissions.get(permission_name) { - vec![permission] - } else { - return Err( - format!("unknown permission {permission_name} for plugin {plugin_name}").into(), - ); - }; - - fn resolve_command( - commands: &mut HashMap, - command: String, - capability: &Capability, - scope_id: usize, - ) { - let resolved = commands - .entry(CommandKey { - name: command, - context: capability.context.clone(), - }) - .or_insert_with(|| ResolvedCommandTemp::default()); - - resolved.windows.extend(capability.windows.clone()); - resolved.scope.push(scope_id); - } - - for permission in permissions { - current_scope_id += 1; - scopes.insert(current_scope_id, permission.inner.scopes.clone()); - - for allowed_command in &permission.inner.commands.allow { - resolve_command( - &mut allowed_commands, - format!("plugin:{plugin_name}|{allowed_command}"), - &capability, - current_scope_id, - ); - } - - for denied_command in &permission.inner.commands.deny { - resolve_command( - &mut denied_commands, - format!("plugin:{plugin_name}|{denied_command}"), - &capability, - current_scope_id, - ); - } - } - } - } - } - - // resolve scopes - let mut resolved_scopes = BTreeMap::new(); - - for allowed in allowed_commands.values_mut() { - allowed.scope.sort(); - - let mut hasher = DefaultHasher::new(); - allowed.scope.hash(&mut hasher); - let hash = hasher.finish() as usize; - - allowed.resolved_scope_key = hash; - - let resolved_scope = ResolvedScope { - allow: allowed - .scope - .iter() - .flat_map(|s| scopes.get(s).unwrap().allow.clone()) - .collect(), - deny: allowed - .scope - .iter() - .flat_map(|s| scopes.get(s).unwrap().deny.clone()) - .collect(), - }; - - resolved_scopes.insert(hash, resolved_scope); - } - - let resolved = Resolved { - allowed_commands: allowed_commands - .into_iter() - .map(|(key, cmd)| { - ( - key, - ResolvedCommand { - windows: cmd.windows, - scope: cmd.resolved_scope_key, - }, - ) - }) - .collect(), - denied_commands: denied_commands - .into_iter() - .map(|(key, cmd)| { - ( - key, - ResolvedCommand { - windows: cmd.windows, - scope: cmd.resolved_scope_key, - }, - ) - }) - .collect(), - scopes: resolved_scopes, - }; - - Ok(resolved) -} - fn ico_icon>( root: &TokenStream, out_dir: &Path, diff --git a/core/tauri-codegen/src/context/resolve_acl.rs b/core/tauri-codegen/src/context/resolve_acl.rs new file mode 100644 index 000000000000..a60d941d64ec --- /dev/null +++ b/core/tauri-codegen/src/context/resolve_acl.rs @@ -0,0 +1,178 @@ +// Copyright 2019-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + +use std::{ + collections::{hash_map::DefaultHasher, BTreeMap, HashMap}, + hash::{Hash, Hasher}, +}; + +use tauri_utils::acl::{ + capability::Capability, + plugin::Manifest, + resolved::{CommandKey, Resolved, ResolvedCommand, ResolvedScope}, + Permission, +}; + +#[derive(Debug, Default)] +struct ResolvedCommandTemp { + pub windows: Vec, + pub scope: Vec, + pub resolved_scope_key: usize, +} + +pub fn resolve( + acl: HashMap, + capabilities: HashMap, +) -> Result> { + let mut allowed_commands = HashMap::new(); + let mut denied_commands = HashMap::new(); + + let mut current_scope_id = 0; + let mut scopes = HashMap::new(); + + // resolve commands + for capability in capabilities.values() { + for permission_id in &capability.permissions { + let permission_name = permission_id.get_base(); + + if let Some(plugin_name) = permission_id.get_prefix() { + let permissions = get_permissions(plugin_name, permission_name, &acl)?; + + for permission in permissions { + current_scope_id += 1; + scopes.insert(current_scope_id, permission.inner.scopes.clone()); + + for allowed_command in &permission.inner.commands.allow { + resolve_command( + &mut allowed_commands, + format!("plugin:{plugin_name}|{allowed_command}"), + capability, + current_scope_id, + ); + } + + for denied_command in &permission.inner.commands.deny { + resolve_command( + &mut denied_commands, + format!("plugin:{plugin_name}|{denied_command}"), + capability, + current_scope_id, + ); + } + } + } + } + } + + // resolve scopes + let mut resolved_scopes = BTreeMap::new(); + + for allowed in allowed_commands.values_mut() { + allowed.scope.sort(); + + let mut hasher = DefaultHasher::new(); + allowed.scope.hash(&mut hasher); + let hash = hasher.finish() as usize; + + allowed.resolved_scope_key = hash; + + let resolved_scope = ResolvedScope { + allow: allowed + .scope + .iter() + .flat_map(|s| scopes.get(s).unwrap().allow.clone()) + .collect(), + deny: allowed + .scope + .iter() + .flat_map(|s| scopes.get(s).unwrap().deny.clone()) + .collect(), + }; + + resolved_scopes.insert(hash, resolved_scope); + } + + let resolved = Resolved { + allowed_commands: allowed_commands + .into_iter() + .map(|(key, cmd)| { + ( + key, + ResolvedCommand { + windows: cmd.windows, + scope: cmd.resolved_scope_key, + }, + ) + }) + .collect(), + denied_commands: denied_commands + .into_iter() + .map(|(key, cmd)| { + ( + key, + ResolvedCommand { + windows: cmd.windows, + scope: cmd.resolved_scope_key, + }, + ) + }) + .collect(), + scopes: resolved_scopes, + }; + + Ok(resolved) +} + +fn resolve_command( + commands: &mut HashMap, + command: String, + capability: &Capability, + scope_id: usize, +) { + let resolved = commands + .entry(CommandKey { + name: command, + context: capability.context.clone(), + }) + .or_insert_with(ResolvedCommandTemp::default); + + resolved.windows.extend(capability.windows.clone()); + resolved.scope.push(scope_id); +} + +fn get_permissions<'a>( + plugin_name: &'a str, + permission_name: &'a str, + acl: &'a HashMap, +) -> Result, String> { + let manifest = acl.get(plugin_name).ok_or_else(|| { + format!( + "unknown plugin {plugin_name}, expected one of {:?}", + acl.keys().cloned().collect::>().join(", ") + ) + })?; + + if permission_name == "default" { + Ok(vec![manifest.default_permission.as_ref().ok_or_else( + || format!("plugin {plugin_name} has no default permission"), + )?]) + } else if let Some(set) = manifest.permission_sets.get(permission_name) { + let mut resolved = Vec::new(); + for p in &set.permissions { + resolved.push( + manifest + .permissions + .get(p) + .ok_or_else(|| format!("permission {p} in set {permission_name} not found"))?, + ); + } + Ok(resolved) + } else if let Some(permission) = manifest.permissions.get(permission_name) { + Ok(vec![permission]) + } else { + Err(format!( + "unknown permission {permission_name} for plugin {plugin_name}" + )) + } +} diff --git a/core/tauri-utils/src/acl/capability.rs b/core/tauri-utils/src/acl/capability.rs index ecc48a026ef3..fae5f78c4dbb 100644 --- a/core/tauri-utils/src/acl/capability.rs +++ b/core/tauri-utils/src/acl/capability.rs @@ -18,12 +18,19 @@ pub struct CapabilitySet { /// Windows can be added to a capability by exact name or glob patterns like *, admin-* or main-window. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Capability { + /// Identifier of the capability. pub identifier: String, + /// 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 wheter it is allowed or not and its scope. #[serde(default)] pub context: CapabilityContext, + /// List of windows that uses this capability. Can be a glob pattern. pub windows: Vec, + /// List of permissions attached to this capability. Must include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`. pub permissions: Vec, } diff --git a/core/tauri-utils/src/acl/mod.rs b/core/tauri-utils/src/acl/mod.rs index faa13d3f0fe3..9399a3d4c7e1 100644 --- a/core/tauri-utils/src/acl/mod.rs +++ b/core/tauri-utils/src/acl/mod.rs @@ -1,3 +1,9 @@ +// Copyright 2019-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + +//! Access Control List types. + use serde::{Deserialize, Serialize}; use std::num::NonZeroU64; diff --git a/core/tauri-utils/src/acl/plugin.rs b/core/tauri-utils/src/acl/plugin.rs index 8f69253fda46..beb6b7938609 100644 --- a/core/tauri-utils/src/acl/plugin.rs +++ b/core/tauri-utils/src/acl/plugin.rs @@ -1,3 +1,5 @@ +//! Plugin ACL types. + use std::collections::HashMap; use super::{Permission, PermissionSet}; diff --git a/core/tauri-utils/src/acl/resolved.rs b/core/tauri-utils/src/acl/resolved.rs index 34c84fe387d9..9037e168b745 100644 --- a/core/tauri-utils/src/acl/resolved.rs +++ b/core/tauri-utils/src/acl/resolved.rs @@ -1,34 +1,51 @@ +//! Resolved ACL for runtime usage. + use std::collections::BTreeMap; use serde::{Deserialize, Serialize}; use super::{capability::CapabilityContext, Value}; +/// A key for a scope, used to link a [`ResolvedCommand#structfield.scope`] to the store [`Resolved#structfield.scopes`]. pub type ScopeKey = usize; +/// A resolved command permission. pub struct ResolvedCommand { + /// The list of window label patterns that is allowed to run this command. pub windows: Vec, + /// The reference of the scope that is associated with this command. See [`Resolved#structfield.scopes`]. pub scope: ScopeKey, } +/// A resolved scope. Contains all scopes defined for a single command. pub struct ResolvedScope where T: Serialize, for<'de> T: Deserialize<'de>, { + /// Allows something on the command. pub allow: Vec, + /// Denies something on the command. pub deny: Vec, } +/// A command key for the map of allowed and denied commands. +/// Takes into consideration the command name and the execution context. #[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct CommandKey { + /// The full command name. pub name: String, + /// The context of the command. pub context: CapabilityContext, } +/// Resolved access control list. pub struct Resolved { + /// The commands that are allowed. Map each command with its context to a [`ResolvedCommand`]. pub allowed_commands: BTreeMap, + /// The commands that are denied. Map each command with its context to a [`ResolvedCommand`]. pub denied_commands: BTreeMap, + /// The store of scopes referenced by a [`ResolvedCommand`]. pub scopes: BTreeMap>, } @@ -64,7 +81,7 @@ mod build { } Self::Remote { dangerous_remote } => { let dangerous_remote = vec_lit(dangerous_remote, str_lit); - quote! { #prefix::Remote { dangerous_remote } } + quote! { #prefix::Remote { dangerous_remote: #dangerous_remote } } } }); } diff --git a/core/tauri-utils/src/acl/value.rs b/core/tauri-utils/src/acl/value.rs index cb5d8f49704f..cb5b5280ebdf 100644 --- a/core/tauri-utils/src/acl/value.rs +++ b/core/tauri-utils/src/acl/value.rs @@ -1,3 +1,6 @@ +//! A [`Value`] that is used instead of [`toml::Value`] or [`serde_json::Value`] +//! to support both formats. + use std::collections::BTreeMap; use std::fmt::Debug; diff --git a/tooling/cli/Cargo.lock b/tooling/cli/Cargo.lock index b05f4a7346d8..b02b41f939fc 100644 --- a/tooling/cli/Cargo.lock +++ b/tooling/cli/Cargo.lock @@ -4884,7 +4884,6 @@ dependencies = [ "json5", "kuchikiki", "log", - "matchit", "memchr", "phf 0.11.2", "schemars", From 60774d5a0e7a6e149142e2a6415d2bde70a6b393 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Thu, 11 Jan 2024 12:55:34 -0300 Subject: [PATCH 15/69] remove command2 stuff --- core/tauri-macros/src/command2.rs | 5 - core/tauri-macros/src/lib.rs | 8 +- core/tauri-macros/src/runtime.rs | 3 +- core/tauri/src/command/authority.rs | 457 ---------------------------- core/tauri/src/lib.rs | 2 + 5 files changed, 4 insertions(+), 471 deletions(-) delete mode 100644 core/tauri-macros/src/command2.rs diff --git a/core/tauri-macros/src/command2.rs b/core/tauri-macros/src/command2.rs deleted file mode 100644 index 7af3a66d66d8..000000000000 --- a/core/tauri-macros/src/command2.rs +++ /dev/null @@ -1,5 +0,0 @@ -use proc_macro::TokenStream; - -pub fn wrapper(attributes: TokenStream, item: TokenStream) -> TokenStream { - todo!() -} diff --git a/core/tauri-macros/src/lib.rs b/core/tauri-macros/src/lib.rs index 21297b37af52..c45f3724d1c9 100644 --- a/core/tauri-macros/src/lib.rs +++ b/core/tauri-macros/src/lib.rs @@ -13,10 +13,9 @@ use crate::context::ContextItems; use proc_macro::TokenStream; -use syn::{parse_macro_input, DeriveInput}; +use syn::parse_macro_input; mod command; -mod command2; mod menu; mod mobile; mod runtime; @@ -35,11 +34,6 @@ pub fn command(attributes: TokenStream, item: TokenStream) -> TokenStream { command::wrapper(attributes, item) } -#[proc_macro_attribute] -pub fn command2(attributes: TokenStream, item: TokenStream) -> TokenStream { - command2::wrapper(attributes, item) -} - #[proc_macro_attribute] pub fn mobile_entry_point(attributes: TokenStream, item: TokenStream) -> TokenStream { mobile::entry_point(attributes, item) diff --git a/core/tauri-macros/src/runtime.rs b/core/tauri-macros/src/runtime.rs index fbe74aa0ccc9..94bcf89ef7d5 100644 --- a/core/tauri-macros/src/runtime.rs +++ b/core/tauri-macros/src/runtime.rs @@ -6,8 +6,7 @@ use proc_macro2::TokenStream; use quote::{quote, ToTokens}; use syn::parse::{Parse, ParseStream}; use syn::{ - parse_quote, DeriveInput, Error, GenericParam, Ident, ItemFn, ItemTrait, ItemType, Token, Type, - TypeParam, + parse_quote, DeriveInput, Error, GenericParam, Ident, ItemTrait, ItemType, Token, Type, TypeParam, }; #[derive(Clone)] diff --git a/core/tauri/src/command/authority.rs b/core/tauri/src/command/authority.rs index 11d84c543dc1..e0acc4b98934 100644 --- a/core/tauri/src/command/authority.rs +++ b/core/tauri/src/command/authority.rs @@ -1,46 +1,15 @@ -use std::any::Any; use std::collections::BTreeMap; use std::fmt::Debug; -use std::future::{ready, Future}; -use std::marker::PhantomData; -use std::pin::Pin; -use std::sync::Arc; use serde::de::DeserializeOwned; -use serde::{Deserialize, Serialize}; use state::TypeMap; use serde_json::Value; -use tauri_macros::default_runtime; - -use crate::command; -use crate::{Runtime, RuntimeHandle}; - -/// Alias for `Result`. -pub type Result = ::std::result::Result; - -#[default_runtime(crate::WryHandle, wry)] -pub type CommandHandle = fn(Box, CommandRequest) -> Result; - -pub struct Caps; pub struct RuntimeAuthority { - caps: Caps, cmds: (), } -#[derive(Debug)] -pub enum Error { - NotFound, - StateEmpty, - StateType, - Scope, -} - -pub trait IntoCommandResponse { - fn into_command_response(self) -> CommandResponse; -} - #[derive(Debug, Default)] pub struct RuntimeAuthorityScope { raw: BTreeMap, @@ -68,430 +37,4 @@ impl RuntimeAuthorityScope { } } -macro_rules! command { - ($command:ident) => { - $command!() - }; -} - -#[command] -fn test(string: String) -> String { - string -} - -macro_rules! test { - () => {{ - struct Cmd; - - impl StrictCommand for Cmd { - type Scope = WeakScope; - type Response = CommandResponse; - - fn name(&self) -> &'static str { - "test" - } - - fn handle( - &self, - _scope: &Self::Scope, - request: CommandRequest, - ) -> Result { - let arg1 = CommandArg::from_command(CommandItem { - name: "test", - key: "string", - message: &request.msg, - }) - .unwrap(); - - test(arg1); - - Ok(CommandResponse) - } - } - - Box::new(Cmd) - }}; -} - trait Scoped: Send + Sync + DeserializeOwned {} - -#[derive(Debug, Deserialize)] -struct WeakScope; - -impl Scoped for WeakScope {} - -impl Scoped for () {} - -impl<'a> TryFrom<&'a RuntimeAuthorityScope> for &'a WeakScope { - type Error = Error; - - fn try_from(value: &'a RuntimeAuthorityScope) -> ::std::result::Result { - value.get_typed("weak-scope").ok_or(Error::NotFound) - } -} - -#[default_runtime(crate::WryHandle, wry)] -struct CommandRequest { - scope: Arc, - //msg: InvokeMessage, - msg: String, - _m: PhantomData, -} - -pub struct CommandResponse(String); - -impl IntoCommandResponse for S -where - S: Serialize, -{ - fn into_command_response(self: S) -> CommandResponse { - CommandResponse(serde_json::to_string(&self).unwrap()) - } -} - -#[default_runtime(crate::WryHandle, wry)] -trait Command { - fn name(&self) -> &'static str; - - fn handler(&self) -> fn(CommandRequest) -> Result; - - //fn handle(&self, request: CommandRequest) -> Result; -} - -#[cfg(feature = "wry")] -static_assertions::assert_obj_safe!(Command); - -#[default_runtime(crate::WryHandle, wry)] -trait StrictCommand { - type Scope: Scoped + Debug + 'static; - type Response: IntoCommandResponse; - - fn name() -> &'static str; - - fn handle(scope: &Self::Scope, request: CommandRequest) -> Result; -} - -fn strict_handler>( - request: CommandRequest, -) -> Result { - let scopes = dbg!(request.scope.clone()); - let scope = dbg!(scopes.get_typed::(T::name())).unwrap(); - T::handle(scope, request).map(IntoCommandResponse::into_command_response) -} - -impl Command for T -where - R: RuntimeHandle, - T: StrictCommand, -{ - fn name(&self) -> &'static str { - T::name() - } - - fn handler(&self) -> fn(CommandRequest) -> Result { - strict_handler:: - } -} - -struct Echo; - -impl Scoped for String {} - -impl StrictCommand for Echo { - type Scope = String; - type Response = String; - - fn name() -> &'static str { - "echo" - } - - fn handle(scope: &Self::Scope, request: CommandRequest) -> Result { - assert_eq!(scope, "ECHO"); - Ok("THIS IS AN ECHO".into()) - } -} - -pub type VCmdState = Arc; - -#[default_runtime(crate::WryHandle, wry)] -pub type VCmdHandle = fn(Option, CommandRequest) -> VCmdFuture; - -pub type VCmdFuture = Pin> + Send>>; - -#[default_runtime(crate::WryHandle, wry)] -struct CommandInner { - name: &'static str, - state: Option, - handle: VCmdHandle, -} - -impl Clone for CommandInner { - #[inline(always)] - fn clone(&self) -> Self { - Self { - name: self.name, - state: self.state.clone(), - handle: self.handle, - } - } -} - -#[default_runtime(crate::WryHandle, wry)] -pub struct VCmd { - inner: CommandInner, -} - -impl VCmd { - #[inline] - pub fn new(name: &'static str, handle: VCmdHandle) -> Self { - Self { - inner: CommandInner { - name, - handle, - state: None, - }, - } - } - - #[inline] - pub fn with_state(name: &'static str, handle: VCmdHandle, state: Arc) -> Self - where - T: Any + Send + Sync, - { - Self { - inner: CommandInner { - name, - handle, - state: Some(state), - }, - } - } - - #[inline] - pub fn handler(&self) -> VCmdHandler { - VCmdHandler { - inner: self.inner.clone(), - } - } -} - -#[default_runtime(crate::WryHandle, wry)] -pub struct VCmdHandler { - inner: CommandInner, -} - -impl VCmdHandler { - #[inline(always)] - pub fn handle(self, request: CommandRequest) -> VCmdFuture { - (self.inner.handle)(self.inner.state, request) - } -} - -#[default_runtime(crate::WryHandle, wry)] -pub struct VCmds(BTreeMap<&'static str, VCmd>); - -impl>>> From for VCmds { - fn from(value: T) -> Self { - Self(value.into()) - } -} - -#[default_runtime(crate::WryHandle, wry)] -pub trait IntoCommand: Sized { - fn into_command(self) -> VCmd; -} - -pub trait IntoCommandResult { - fn into_command_result(self) -> Result; -} - -impl IntoCommandResult for Result -where - T: IntoCommandResponse, -{ - #[inline(always)] - fn into_command_result(self) -> Result { - self.map(IntoCommandResponse::into_command_response) - } -} - -#[default_runtime(crate::WryHandle, wry)] -pub trait FunctionalCommand { - type Scope: Scoped + Debug + 'static; - - fn nname() -> &'static str; - - fn handle(scope: &Self::Scope, request: CommandRequest) -> VCmdFuture; - - fn into_command(self) -> VCmd - where - Self: Sized, - { - fn handle(_state: Option, request: CommandRequest) -> VCmdFuture - where - T: FunctionalCommand, - R: RuntimeHandle, - { - let scopes = request.scope.clone(); - let scope = scopes.get_typed::(T::nname()).unwrap(); - T::handle(scope, request) - } - - VCmd::new(Self::nname(), handle::) - } -} - -#[default_runtime(crate::WryHandle, wry)] -pub trait StatefulCommand { - type Scope: Scoped + Debug + 'static; - - fn nname() -> &'static str; - - fn handle(self: Arc, scope: &Self::Scope, request: CommandRequest) -> VCmdFuture; - - fn into_command(self) -> VCmd - where - Self: Send + Sync + Sized + 'static, - { - fn handle(state: Option, request: CommandRequest) -> VCmdFuture - where - T: StatefulCommand + Send + Sync + 'static, - R: RuntimeHandle, - { - Box::pin(async move { - let scopes = request.scope.clone(); - let scope = scopes - .get_typed::(T::nname()) - .ok_or(Error::Scope)?; - - let state = state - .ok_or(Error::StateEmpty)? - .downcast() - .map_err(|_| Error::StateType)?; - - T::handle(state, scope, request).await - }) - } - - VCmd::with_state(Self::nname(), handle::, Arc::new(self)) - } -} - -fn echo() -> VCmd { - VCmd::new("echo", |_, _r| { - Box::pin(async move { Ok(CommandResponse("THIS IS AN ECHO".into())) }) - }) -} - -struct E; - -impl FunctionalCommand for E { - type Scope = String; - - fn nname() -> &'static str { - "echo" - } - - fn handle(scope: &Self::Scope, request: CommandRequest) -> VCmdFuture { - Box::pin(ready(Ok(CommandResponse(request.msg)))) - } -} - -struct PE(String); - -impl StatefulCommand for PE { - type Scope = String; - - fn nname() -> &'static str { - "echo_prefix" - } - - fn handle(self: Arc, _: &Self::Scope, request: CommandRequest) -> VCmdFuture { - Box::pin(ready(Ok(CommandResponse(format!( - "{}: {}", - self.0, request.msg - ))))) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - fn req(scope: impl Into>) -> CommandRequest { - CommandRequest { - scope: Arc::new(RuntimeAuthorityScope { - raw: scope.into(), - cache: Default::default(), - }), - msg: "invoke message".into(), - _m: PhantomData, - } - } - - #[tokio::test] - async fn echo_vcmd() { - let request = req([]); - let echo = super::echo(); - //let cmds = VCmds::from([(echo.name, echo)]); - - let handler = echo.handler(); - crate::async_runtime::spawn(async move { - assert_eq!( - handler.handle(request).await.unwrap().0, - String::from("THIS IS AN ECHO") - ); - }) - .await - .unwrap(); - } - - #[tokio::test] - async fn echo_functional() { - let echo = E; - let request = req([("echo".into(), Value::String("ECHO".into()))]); - let cmd = echo.into_command(); - let handler = cmd.handler(); - crate::async_runtime::spawn(async move { - assert_eq!( - handler.handle(request).await.unwrap().0, - String::from("invoke message") - ); - }) - .await - .unwrap(); - } - - #[tokio::test] - async fn echo_stateful() { - let echo = PE("prefix".into()); - let request = req([("echo_prefix".into(), Value::String("ECHO".into()))]); - let cmd = echo.into_command(); - let handler = cmd.handler(); - crate::async_runtime::spawn(async move { - assert_eq!( - handler.handle(request).await.unwrap().0, - String::from("prefix: invoke message") - ); - }) - .await - .unwrap(); - } - - #[tokio::test] - async fn echo() { - let cmd: Box + Send + Sync> = Box::new(Echo); - let request = req([(cmd.name().into(), Value::String("ECHO".into()))]); - let handler = dbg!(cmd.handler()); - - assert_eq!(cmd.name(), "echo"); - crate::async_runtime::spawn(async move { - assert_eq!( - handler(request).unwrap().0, - String::from("\"THIS IS AN ECHO\"") - ); - }) - .await - .unwrap(); - } -} diff --git a/core/tauri/src/lib.rs b/core/tauri/src/lib.rs index 779d61950443..29a19b8f2a57 100644 --- a/core/tauri/src/lib.rs +++ b/core/tauri/src/lib.rs @@ -110,6 +110,7 @@ pub use http; #[cfg(feature = "wry")] #[cfg_attr(docsrs, doc(cfg(feature = "wry")))] pub type Wry = tauri_runtime_wry::Wry; +/// A Tauri [`RuntimeHandle`] wrapper around wry. #[cfg(feature = "wry")] #[cfg_attr(docsrs, doc(cfg(feature = "wry")))] pub type WryHandle = tauri_runtime_wry::WryHandle; @@ -276,6 +277,7 @@ pub enum EventLoopMessage { /// The webview runtime interface. A wrapper around [`runtime::Runtime`] with the proper user event type associated. pub trait Runtime: runtime::Runtime {} +/// The webview runtime handle. A wrapper arond [`runtime::RuntimeHandle`] with the proper user event type associated. pub trait RuntimeHandle: runtime::RuntimeHandle {} impl> Runtime for W {} From 650829b61158836e8d3afafaa37cf9da0a0a554b Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Thu, 11 Jan 2024 13:31:23 -0300 Subject: [PATCH 16/69] actually check runtime authority --- core/tauri-codegen/src/context/resolve_acl.rs | 36 +++++++---- core/tauri-plugin/src/build/acl.rs | 3 +- core/tauri-utils/src/acl/mod.rs | 37 ++++++++++++ core/tauri-utils/src/acl/resolved.rs | 60 +------------------ core/tauri-utils/src/acl/value.rs | 49 +++++++++++++++ core/tauri-utils/src/tokens.rs | 2 + core/tauri/src/command/authority.rs | 47 ++++++++++++--- core/tauri/src/command/mod.rs | 2 + core/tauri/src/manager/mod.rs | 3 + core/tauri/src/window/mod.rs | 19 ++++++ examples/api/src-tauri/build.rs | 3 +- 11 files changed, 182 insertions(+), 79 deletions(-) diff --git a/core/tauri-codegen/src/context/resolve_acl.rs b/core/tauri-codegen/src/context/resolve_acl.rs index a60d941d64ec..3fce40916a77 100644 --- a/core/tauri-codegen/src/context/resolve_acl.rs +++ b/core/tauri-codegen/src/context/resolve_acl.rs @@ -8,10 +8,10 @@ use std::{ }; use tauri_utils::acl::{ - capability::Capability, + capability::{Capability, CapabilityContext}, plugin::Manifest, resolved::{CommandKey, Resolved, ResolvedCommand, ResolvedScope}, - Permission, + ExecutionContext, Permission, }; #[derive(Debug, Default)] @@ -130,15 +130,29 @@ fn resolve_command( capability: &Capability, scope_id: usize, ) { - let resolved = commands - .entry(CommandKey { - name: command, - context: capability.context.clone(), - }) - .or_insert_with(ResolvedCommandTemp::default); - - resolved.windows.extend(capability.windows.clone()); - resolved.scope.push(scope_id); + let contexts = match &capability.context { + CapabilityContext::Local => { + vec![ExecutionContext::Local] + } + CapabilityContext::Remote { dangerous_remote } => dangerous_remote + .iter() + .map(|domain| ExecutionContext::Remote { + domain: domain.to_string(), + }) + .collect(), + }; + + for context in contexts { + let resolved = commands + .entry(CommandKey { + name: command.clone(), + context, + }) + .or_default(); + + resolved.windows.extend(capability.windows.clone()); + resolved.scope.push(scope_id); + } } fn get_permissions<'a>( diff --git a/core/tauri-plugin/src/build/acl.rs b/core/tauri-plugin/src/build/acl.rs index 5fc66f237f00..c9dd90360cf6 100644 --- a/core/tauri-plugin/src/build/acl.rs +++ b/core/tauri-plugin/src/build/acl.rs @@ -45,8 +45,7 @@ pub struct PermissionFile { pub fn define_permissions(pattern: &str) -> Result<(), Error> { let permission_files = glob::glob(pattern)? .flatten() - .map(|p| p.canonicalize()) - .flatten() + .flat_map(|p| p.canonicalize()) .collect::>(); for path in &permission_files { diff --git a/core/tauri-utils/src/acl/mod.rs b/core/tauri-utils/src/acl/mod.rs index 9399a3d4c7e1..afe5eb734b84 100644 --- a/core/tauri-utils/src/acl/mod.rs +++ b/core/tauri-utils/src/acl/mod.rs @@ -87,3 +87,40 @@ pub struct PermissionSet { /// All permissions this set contains. pub permissions: Vec, } + +/// Execution context of an IPC call. +#[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +pub enum ExecutionContext { + /// A local URL is used (the Tauri app URL). + Local, + /// Remote URL is tring to use the IPC. + Remote { + /// The domain trying to access the IPC. + domain: String, + }, +} + +#[cfg(feature = "build")] +mod build { + use crate::tokens::*; + + use super::*; + use proc_macro2::TokenStream; + use quote::{quote, ToTokens, TokenStreamExt}; + + impl ToTokens for ExecutionContext { + fn to_tokens(&self, tokens: &mut TokenStream) { + let prefix = quote! { ::tauri::utils::acl::ExecutionContext }; + + tokens.append_all(match self { + Self::Local => { + quote! { #prefix::Local } + } + Self::Remote { domain } => { + let domain = str_lit(domain); + quote! { #prefix::Remote { domain: #domain } } + } + }); + } + } +} diff --git a/core/tauri-utils/src/acl/resolved.rs b/core/tauri-utils/src/acl/resolved.rs index 9037e168b745..6bd37023dfc8 100644 --- a/core/tauri-utils/src/acl/resolved.rs +++ b/core/tauri-utils/src/acl/resolved.rs @@ -4,7 +4,7 @@ use std::collections::BTreeMap; use serde::{Deserialize, Serialize}; -use super::{capability::CapabilityContext, Value}; +use super::{ExecutionContext, Value}; /// A key for a scope, used to link a [`ResolvedCommand#structfield.scope`] to the store [`Resolved#structfield.scopes`]. pub type ScopeKey = usize; @@ -36,7 +36,7 @@ pub struct CommandKey { /// The full command name. pub name: String, /// The context of the command. - pub context: CapabilityContext, + pub context: ExecutionContext, } /// Resolved access control list. @@ -56,7 +56,7 @@ mod build { use std::convert::identity; use super::*; - use crate::{acl::Number, tokens::*}; + use crate::tokens::*; /// Write a `TokenStream` of the `$struct`'s fields to the `$tokens`. /// @@ -71,22 +71,6 @@ mod build { }; } - 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::Local => { - quote! { #prefix::Local } - } - Self::Remote { dangerous_remote } => { - let dangerous_remote = vec_lit(dangerous_remote, str_lit); - quote! { #prefix::Remote { dangerous_remote: #dangerous_remote } } - } - }); - } - } - impl ToTokens for CommandKey { fn to_tokens(&self, tokens: &mut TokenStream) { let name = str_lit(&self.name); @@ -103,44 +87,6 @@ mod build { } } - impl ToTokens for Number { - fn to_tokens(&self, tokens: &mut TokenStream) { - let prefix = quote! { ::tauri::utils::acl:::Number }; - - tokens.append_all(match self { - Self::Int(i) => { - quote! { #prefix::Int(i) } - } - Self::Float(f) => { - quote! { #prefix::Float (f) } - } - }); - } - } - - impl ToTokens for Value { - fn to_tokens(&self, tokens: &mut TokenStream) { - let prefix = quote! { ::tauri::acl::Value }; - - tokens.append_all(match self { - Value::Bool(bool) => quote! { #prefix::Bool(#bool) }, - Value::Number(number) => quote! { #prefix::Number(#number) }, - Value::String(str) => { - let s = str_lit(str); - quote! { #prefix::String(#s) } - } - Value::List(vec) => { - let items = vec_lit(vec, identity); - quote! { #prefix::Array(#items) } - } - Value::Map(map) => { - let map = map_lit(quote! { ::tauri::acl::Map }, map, str_lit, identity); - quote! { #prefix::Map(#map) } - } - }); - } - } - impl ToTokens for ResolvedScope { fn to_tokens(&self, tokens: &mut TokenStream) { let allow = vec_lit(&self.allow, identity); diff --git a/core/tauri-utils/src/acl/value.rs b/core/tauri-utils/src/acl/value.rs index cb5b5280ebdf..38b24763e2f1 100644 --- a/core/tauri-utils/src/acl/value.rs +++ b/core/tauri-utils/src/acl/value.rs @@ -98,3 +98,52 @@ impl From for Value { } } } + +#[cfg(feature = "build")] +mod build { + use std::convert::identity; + + use crate::tokens::*; + + use super::*; + use proc_macro2::TokenStream; + use quote::{quote, ToTokens, TokenStreamExt}; + + impl ToTokens for Number { + fn to_tokens(&self, tokens: &mut TokenStream) { + let prefix = quote! { ::tauri::utils::acl:::Number }; + + tokens.append_all(match self { + Self::Int(i) => { + quote! { #prefix::Int(#i) } + } + Self::Float(f) => { + quote! { #prefix::Float (#f) } + } + }); + } + } + + impl ToTokens for Value { + fn to_tokens(&self, tokens: &mut TokenStream) { + let prefix = quote! { ::tauri::acl::Value }; + + tokens.append_all(match self { + Value::Bool(bool) => quote! { #prefix::Bool(#bool) }, + Value::Number(number) => quote! { #prefix::Number(#number) }, + Value::String(str) => { + let s = str_lit(str); + quote! { #prefix::String(#s) } + } + Value::List(vec) => { + let items = vec_lit(vec, identity); + quote! { #prefix::Array(#items) } + } + Value::Map(map) => { + let map = map_lit(quote! { ::tauri::acl::Map }, map, str_lit, identity); + quote! { #prefix::Map(#map) } + } + }); + } + } +} diff --git a/core/tauri-utils/src/tokens.rs b/core/tauri-utils/src/tokens.rs index 9a52498ab343..1c01bf5082b6 100644 --- a/core/tauri-utils/src/tokens.rs +++ b/core/tauri-utils/src/tokens.rs @@ -1,3 +1,5 @@ +//! Utilities to implement [`ToTokens`] for a type. + use std::path::Path; use proc_macro2::TokenStream; diff --git a/core/tauri/src/command/authority.rs b/core/tauri/src/command/authority.rs index e0acc4b98934..9b9ff880fe26 100644 --- a/core/tauri/src/command/authority.rs +++ b/core/tauri/src/command/authority.rs @@ -5,27 +5,60 @@ use serde::de::DeserializeOwned; use state::TypeMap; use serde_json::Value; +use tauri_utils::acl::{ + resolved::{CommandKey, Resolved, ResolvedCommand}, + ExecutionContext, +}; +/// The runtime authority used to authorize IPC execution based on the Access Control List. pub struct RuntimeAuthority { - cmds: (), + allowed_commands: BTreeMap, + denied_commands: BTreeMap, } +impl RuntimeAuthority { + pub(crate) fn new(acl: Resolved) -> Self { + Self { + allowed_commands: acl.allowed_commands, + denied_commands: acl.denied_commands, + } + } + + /// Checks if the given IPC execution is allowed. + pub fn is_allowed(&self, command: &str, window: &String, context: ExecutionContext) -> bool { + let key = CommandKey { + name: command.into(), + context, + }; + if self.denied_commands.contains_key(&key) { + false + } else if let Some(allowed) = self.allowed_commands.get(&key) { + allowed.windows.contains(window) + } else { + false + } + } +} + +#[allow(dead_code)] #[derive(Debug, Default)] -pub struct RuntimeAuthorityScope { +pub struct ScopeManager { raw: BTreeMap, cache: TypeMap![Send + Sync], } -impl RuntimeAuthorityScope { - pub fn get_typed(&self, key: &str) -> Option<&T> { +#[allow(dead_code)] +impl ScopeManager { + pub fn get_typed( + &self, + key: &str, + ) -> Option<&T> { match self.cache.try_get() { cached @ Some(_) => cached, - //None => match dbg!(self.raw.get(key).and_then(Value::deserialize::)) { None => match self .raw .get(key) .and_then(|r| dbg!(serde_json::from_value::(dbg!(r.clone()))).ok()) - //.and_then(|r| dbg!(serde_json::from_str::(&r)).ok()) { None => None, Some(value) => { @@ -36,5 +69,3 @@ impl RuntimeAuthorityScope { } } } - -trait Scoped: Send + Sync + DeserializeOwned {} diff --git a/core/tauri/src/command/mod.rs b/core/tauri/src/command/mod.rs index ec766acfb3f0..e009691c2657 100644 --- a/core/tauri/src/command/mod.rs +++ b/core/tauri/src/command/mod.rs @@ -18,6 +18,8 @@ use serde::{ mod authority; +pub use authority::RuntimeAuthority; + /// Represents a custom command. pub struct CommandItem<'a, R: Runtime> { /// The name of the command, e.g. `handler` on `#[command] fn handler(value: u64)` diff --git a/core/tauri/src/manager/mod.rs b/core/tauri/src/manager/mod.rs index c244c240136d..bb2be6cb43c6 100644 --- a/core/tauri/src/manager/mod.rs +++ b/core/tauri/src/manager/mod.rs @@ -22,6 +22,7 @@ use tauri_utils::{ use crate::{ app::{AppHandle, GlobalWindowEventListener, OnPageLoad}, + command::RuntimeAuthority, event::{assert_event_name_is_valid, Event, EventId, Listeners}, ipc::{Invoke, InvokeHandler, InvokeResponder}, plugin::PluginStore, @@ -178,6 +179,7 @@ pub struct Asset { #[default_runtime(crate::Wry, wry)] pub struct AppManager { + pub runtime_authority: RuntimeAuthority, pub window: window::WindowManager, #[cfg(all(desktop, feature = "tray-icon"))] pub tray: tray::TrayManager, @@ -245,6 +247,7 @@ impl AppManager { } Self { + runtime_authority: RuntimeAuthority::new(context.resolved_acl), window: window::WindowManager { windows: Mutex::default(), invoke_handler, diff --git a/core/tauri/src/window/mod.rs b/core/tauri/src/window/mod.rs index d5c3bad684db..fc91d638a668 100644 --- a/core/tauri/src/window/mod.rs +++ b/core/tauri/src/window/mod.rs @@ -8,6 +8,7 @@ pub(crate) mod plugin; use http::HeaderMap; pub use tauri_runtime::window::PageLoadEvent; +use tauri_utils::acl::ExecutionContext; pub use tauri_utils::{config::Color, WindowEffect as Effect, WindowEffectState as EffectState}; use url::Url; @@ -2360,6 +2361,24 @@ impl Window { if !is_local && scope.is_none() { invoke.resolver.reject(scope_not_found_error_message); } else if request.cmd.starts_with("plugin:") { + if !manager.runtime_authority.is_allowed( + &request.cmd, + &invoke.message.window.window.label, + if is_local { + ExecutionContext::Local + } else { + ExecutionContext::Remote { + domain: current_url + .domain() + .map(|d| d.to_string()) + .unwrap_or_default(), + } + }, + ) { + invoke.resolver.reject("NOT ALLOWED"); + return; + } + let command = invoke.message.command.replace("plugin:", ""); let mut tokens = command.split('|'); // safe to unwrap: split always has a least one item diff --git a/examples/api/src-tauri/build.rs b/examples/api/src-tauri/build.rs index 2154ff35f5e3..fb8781fe8079 100644 --- a/examples/api/src-tauri/build.rs +++ b/examples/api/src-tauri/build.rs @@ -3,10 +3,11 @@ // SPDX-License-Identifier: MIT fn main() { + tauri_build::build(); + let mut codegen = tauri_build::CodegenContext::new(); if !cfg!(feature = "custom-protocol") { codegen = codegen.dev(); } codegen.build(); - tauri_build::build(); } From dc42a9dc121c736f715818e146c8daeb3d35d211 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Thu, 11 Jan 2024 13:40:48 -0300 Subject: [PATCH 17/69] small fixes [skip ci] --- core/tauri-utils/src/acl/resolved.rs | 1 + core/tauri/src/window/mod.rs | 30 ++++++++++--------- .../src-tauri/tauri-plugin-sample/src/lib.rs | 15 ++++++++++ .../tauri-plugin-sample/src/models.rs | 2 +- 4 files changed, 33 insertions(+), 15 deletions(-) diff --git a/core/tauri-utils/src/acl/resolved.rs b/core/tauri-utils/src/acl/resolved.rs index 6bd37023dfc8..9ea2b366c075 100644 --- a/core/tauri-utils/src/acl/resolved.rs +++ b/core/tauri-utils/src/acl/resolved.rs @@ -10,6 +10,7 @@ use super::{ExecutionContext, Value}; pub type ScopeKey = usize; /// A resolved command permission. +#[derive(Debug)] pub struct ResolvedCommand { /// The list of window label patterns that is allowed to run this command. pub windows: Vec, diff --git a/core/tauri/src/window/mod.rs b/core/tauri/src/window/mod.rs index fc91d638a668..79afdda978f1 100644 --- a/core/tauri/src/window/mod.rs +++ b/core/tauri/src/window/mod.rs @@ -2361,20 +2361,22 @@ impl Window { if !is_local && scope.is_none() { invoke.resolver.reject(scope_not_found_error_message); } else if request.cmd.starts_with("plugin:") { - if !manager.runtime_authority.is_allowed( - &request.cmd, - &invoke.message.window.window.label, - if is_local { - ExecutionContext::Local - } else { - ExecutionContext::Remote { - domain: current_url - .domain() - .map(|d| d.to_string()) - .unwrap_or_default(), - } - }, - ) { + if request.cmd != crate::ipc::channel::FETCH_CHANNEL_DATA_COMMAND + && !manager.runtime_authority.is_allowed( + &request.cmd, + &invoke.message.window.window.label, + if is_local { + ExecutionContext::Local + } else { + ExecutionContext::Remote { + domain: current_url + .domain() + .map(|d| d.to_string()) + .unwrap_or_default(), + } + }, + ) + { invoke.resolver.reject("NOT ALLOWED"); return; } diff --git a/examples/api/src-tauri/tauri-plugin-sample/src/lib.rs b/examples/api/src-tauri/tauri-plugin-sample/src/lib.rs index 39b2d9a3f5c9..69e69b37b8fe 100644 --- a/examples/api/src-tauri/tauri-plugin-sample/src/lib.rs +++ b/examples/api/src-tauri/tauri-plugin-sample/src/lib.rs @@ -35,6 +35,20 @@ impl> crate::SampleExt for T { } } +#[tauri::command] +fn ping( + app: tauri::AppHandle, + value: Option, +) -> std::result::Result { + app + .sample() + .ping(PingRequest { + value, + on_event: tauri::ipc::Channel::new(|_| Ok(())), + }) + .map_err(|e| e.to_string()) +} + pub fn init() -> TauriPlugin { Builder::new("sample") .setup(|app, api| { @@ -46,6 +60,7 @@ pub fn init() -> TauriPlugin { Ok(()) }) + .invoke_handler(tauri::generate_handler![ping]) .on_navigation(|window, url| { println!("navigation {} {url}", window.label()); true diff --git a/examples/api/src-tauri/tauri-plugin-sample/src/models.rs b/examples/api/src-tauri/tauri-plugin-sample/src/models.rs index 3c824a58912c..02db95608c7e 100644 --- a/examples/api/src-tauri/tauri-plugin-sample/src/models.rs +++ b/examples/api/src-tauri/tauri-plugin-sample/src/models.rs @@ -12,7 +12,7 @@ pub struct PingRequest { pub on_event: Channel, } -#[derive(Debug, Clone, Default, Deserialize)] +#[derive(Debug, Clone, Default, Deserialize, Serialize)] pub struct PingResponse { pub value: Option, } From ddd898c6a9cf07ef7ebafce4ad1261f1fe86c75c Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Thu, 11 Jan 2024 16:32:41 -0300 Subject: [PATCH 18/69] add function to auto generate basic permission for a command [skip ci] --- core/tauri-plugin/src/build/acl.rs | 2 +- core/tauri-plugin/src/build/mod.rs | 97 ++++++++++++++----- .../src-tauri/tauri-plugin-sample/build.rs | 4 +- .../autogenerated/commands/ping.toml | 15 +++ .../tauri-plugin-sample/permissions/ping.toml | 5 - .../plugins/tauri-plugin-example/build.rs | 4 +- 6 files changed, 96 insertions(+), 31 deletions(-) create mode 100644 examples/api/src-tauri/tauri-plugin-sample/permissions/autogenerated/commands/ping.toml delete mode 100644 examples/api/src-tauri/tauri-plugin-sample/permissions/ping.toml diff --git a/core/tauri-plugin/src/build/acl.rs b/core/tauri-plugin/src/build/acl.rs index c9dd90360cf6..6d89fd663d7b 100644 --- a/core/tauri-plugin/src/build/acl.rs +++ b/core/tauri-plugin/src/build/acl.rs @@ -42,7 +42,7 @@ pub struct PermissionFile { pub permission: Option>, } -pub fn define_permissions(pattern: &str) -> Result<(), Error> { +pub(crate) fn define_permissions(pattern: &str) -> Result<(), Error> { let permission_files = glob::glob(pattern)? .flatten() .flat_map(|p| p.canonicalize()) diff --git a/core/tauri-plugin/src/build/mod.rs b/core/tauri-plugin/src/build/mod.rs index 01cd133d6c3a..f5075e6dfcd6 100644 --- a/core/tauri-plugin/src/build/mod.rs +++ b/core/tauri-plugin/src/build/mod.rs @@ -1,3 +1,5 @@ +use std::{fs::create_dir_all, path::Path}; + use cargo_metadata::{Metadata, MetadataCommand}; use thiserror::Error; @@ -44,36 +46,85 @@ pub enum Error { UnknownPermissionFormat(String), } -/// [`try_build`] but will exit automatically if an error is found. -pub fn build(permissions_path_pattern: &str) { - if let Err(error) = try_build(permissions_path_pattern) { - println!("{}: {}", env!("CARGO_PKG_NAME"), error); - std::process::exit(1); - } +pub struct Builder<'a> { + commands: &'a [&'static str], } -/// Ensure this crate is properly configured to be a Tauri plugin. -/// -/// # Errors -/// -/// Errors will occur if environmental variables expected to be set inside of [build scripts] -/// are not found, or if the crate violates Tauri plugin conventions. -pub fn try_build(permissions_path_pattern: &str) -> Result<(), Error> { - // convention: plugin names should not use underscores - let name = build_var("CARGO_PKG_NAME")?; - if name.contains('_') { - return Err(Error::CrateName); +impl<'a> Builder<'a> { + pub fn new(commands: &'a [&'static str]) -> Self { + Self { commands } + } + + /// [`Self::try_build`] but will exit automatically if an error is found. + pub fn build(self) { + if let Err(error) = self.try_build() { + println!("{}: {}", env!("CARGO_PKG_NAME"), error); + std::process::exit(1); + } } - // requirement: links MUST be set and MUST match the name - let _links = build_var("CARGO_MANIFEST_LINKS")?; + /// Ensure this crate is properly configured to be a Tauri plugin. + /// + /// # Errors + /// + /// Errors will occur if environmental variables expected to be set inside of [build scripts] + /// are not found, or if the crate violates Tauri plugin conventions. + pub fn try_build(self) -> Result<(), Error> { + // convention: plugin names should not use underscores + let name = build_var("CARGO_PKG_NAME")?; + if name.contains('_') { + return Err(Error::CrateName); + } + + // requirement: links MUST be set and MUST match the name + let _links = build_var("CARGO_MANIFEST_LINKS")?; + + let autogenerated = Path::new("permissions/autogenerated/"); + let commands_dir = &autogenerated.join("commands"); + + if !self.commands.is_empty() { + autogenerate_command_permissions(&commands_dir, self.commands); + } - acl::define_permissions(permissions_path_pattern)?; + acl::define_permissions("./permissions/**/*.*")?; - let metadata = find_metadata()?; - println!("{metadata:#?}"); + let metadata = find_metadata()?; + println!("{metadata:#?}"); - Ok(()) + Ok(()) + } +} + +fn autogenerate_command_permissions(path: &Path, commands: &[&str]) { + if !path.exists() { + create_dir_all(path).expect("unable to create autogenerated commands dir"); + } + + for command in commands { + let slugified_command = command.replace("_", "-"); + let toml = format!( + r###"# Automatically generated - DO NOT EDIT! + +[[permission]] +identifier = "allow-{slugified_command}" +description = "This enables the {command} command without any pre-configured scope." +commands.allow = [ + "{command}" +] + +[[permission]] +identifier = "deny-{slugified_command}" +description = "This denies the {command} command without any pre-configured scope." +commands.deny = [ + "{command}" +]"###, + command = command, + slugified_command = slugified_command + ); + + std::fs::write(path.join(format!("{command}.toml")), toml) + .expect(&format!("unable to autogenerate ${command}.toml")); + } } /// Grab an env var that is expected to be set inside of build scripts. diff --git a/examples/api/src-tauri/tauri-plugin-sample/build.rs b/examples/api/src-tauri/tauri-plugin-sample/build.rs index d62b8d414128..64afa2311a22 100644 --- a/examples/api/src-tauri/tauri-plugin-sample/build.rs +++ b/examples/api/src-tauri/tauri-plugin-sample/build.rs @@ -4,6 +4,8 @@ use std::process::exit; +const COMMANDS: &[&str] = &["ping"]; + fn main() { if let Err(error) = tauri_build::mobile::PluginBuilder::new() .android_path("android") @@ -14,5 +16,5 @@ fn main() { exit(1); } - tauri_plugin::build("./permissions/**/*.toml"); + tauri_plugin::Builder::new(COMMANDS).build(); } diff --git a/examples/api/src-tauri/tauri-plugin-sample/permissions/autogenerated/commands/ping.toml b/examples/api/src-tauri/tauri-plugin-sample/permissions/autogenerated/commands/ping.toml new file mode 100644 index 000000000000..069ae2db6df6 --- /dev/null +++ b/examples/api/src-tauri/tauri-plugin-sample/permissions/autogenerated/commands/ping.toml @@ -0,0 +1,15 @@ +# Automatically generated - DO NOT EDIT! + +[[permission]] +identifier = "allow-ping" +description = "This enables the ping command without any pre-configured scope." +commands.allow = [ + "ping" +] + +[[permission]] +identifier = "deny-ping" +description = "This denies the ping command without any pre-configured scope." +commands.deny = [ + "ping" +] \ No newline at end of file diff --git a/examples/api/src-tauri/tauri-plugin-sample/permissions/ping.toml b/examples/api/src-tauri/tauri-plugin-sample/permissions/ping.toml deleted file mode 100644 index dbddd0cac1da..000000000000 --- a/examples/api/src-tauri/tauri-plugin-sample/permissions/ping.toml +++ /dev/null @@ -1,5 +0,0 @@ -[[permission]] -version = 1 -identifier = "allow-ping" -description = "This allows using the ping command." -commands.allow = ["ping"] diff --git a/examples/plugins/tauri-plugin-example/build.rs b/examples/plugins/tauri-plugin-example/build.rs index 2ecf0ac89967..f33c1bfad2e2 100644 --- a/examples/plugins/tauri-plugin-example/build.rs +++ b/examples/plugins/tauri-plugin-example/build.rs @@ -1,3 +1,5 @@ +const COMMANDS: &[&str] = &[]; + fn main() { - tauri_plugin::build("./permissions/**/*.toml") + tauri_plugin::Builder::new(COMMANDS).build() } From dadb3d1df34350f27b710d6446691bfce649bf74 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Sat, 13 Jan 2024 14:06:43 -0300 Subject: [PATCH 19/69] retrieve command scope, implement CommandArg [skip ci] --- core/tauri-build/src/acl.rs | 2 +- core/tauri-codegen/src/context/resolve_acl.rs | 4 +- core/tauri-macros/src/command/wrapper.rs | 31 ++++-- core/tauri-plugin/src/build/acl.rs | 2 +- core/tauri-utils/src/acl/mod.rs | 2 +- core/tauri-utils/src/acl/resolved.rs | 27 ++--- core/tauri-utils/src/acl/value.rs | 17 ++- core/tauri/src/command/authority.rs | 104 ++++++++++++++---- core/tauri/src/command/mod.rs | 6 +- core/tauri/src/ipc/mod.rs | 4 + core/tauri/src/window/mod.rs | 36 +++--- .../api/src-tauri/capabilities/run-app.toml | 2 +- .../permissions/ping-scoped.toml | 6 + .../src-tauri/tauri-plugin-sample/src/lib.rs | 10 ++ 14 files changed, 182 insertions(+), 71 deletions(-) create mode 100644 examples/api/src-tauri/tauri-plugin-sample/permissions/ping-scoped.toml diff --git a/core/tauri-build/src/acl.rs b/core/tauri-build/src/acl.rs index e761d7e9c75c..323a43b43002 100644 --- a/core/tauri-build/src/acl.rs +++ b/core/tauri-build/src/acl.rs @@ -62,7 +62,7 @@ pub(crate) fn get_plugin_manifests() -> Result> { version: default.version, description: default.description, commands: default.commands, - scopes: default.scopes, + scope: default.scope, }, }); } diff --git a/core/tauri-codegen/src/context/resolve_acl.rs b/core/tauri-codegen/src/context/resolve_acl.rs index 3fce40916a77..7c1c905f68d4 100644 --- a/core/tauri-codegen/src/context/resolve_acl.rs +++ b/core/tauri-codegen/src/context/resolve_acl.rs @@ -41,7 +41,7 @@ pub fn resolve( for permission in permissions { current_scope_id += 1; - scopes.insert(current_scope_id, permission.inner.scopes.clone()); + scopes.insert(current_scope_id, permission.inner.scope.clone()); for allowed_command in &permission.inner.commands.allow { resolve_command( @@ -118,7 +118,7 @@ pub fn resolve( ) }) .collect(), - scopes: resolved_scopes, + scope: resolved_scopes, }; Ok(resolved) diff --git a/core/tauri-macros/src/command/wrapper.rs b/core/tauri-macros/src/command/wrapper.rs index c28c74c0fa6d..187507d0108e 100644 --- a/core/tauri-macros/src/command/wrapper.rs +++ b/core/tauri-macros/src/command/wrapper.rs @@ -120,6 +120,7 @@ enum ArgumentCase { struct Invoke { message: Ident, resolver: Ident, + acl: Ident, } /// Create a new [`Wrapper`] from the function and the generated code parsed from the function. @@ -142,6 +143,7 @@ pub fn wrapper(attributes: TokenStream, item: TokenStream) -> TokenStream { let invoke = Invoke { message: format_ident!("__tauri_message__"), resolver: format_ident!("__tauri_resolver__"), + acl: format_ident!("__tauri_acl__"), }; // Tauri currently doesn't support async commands that take a reference as input and don't return @@ -210,7 +212,11 @@ pub fn wrapper(attributes: TokenStream, item: TokenStream) -> TokenStream { } }; - let Invoke { message, resolver } = invoke; + let Invoke { + message, + resolver, + acl, + } = invoke; let root = attrs.root; @@ -255,7 +261,7 @@ pub fn wrapper(attributes: TokenStream, item: TokenStream) -> TokenStream { use #root::command::private::*; // prevent warnings when the body is a `compile_error!` or if the command has no arguments #[allow(unused_variables)] - let #root::ipc::Invoke { message: #message, resolver: #resolver } = $invoke; + let #root::ipc::Invoke { message: #message, resolver: #resolver, acl: #acl } = $invoke; #maybe_span @@ -280,8 +286,12 @@ fn body_async( invoke: &Invoke, attributes: &WrapperAttributes, ) -> syn::Result { - let Invoke { message, resolver } = invoke; - parse_args(function, message, attributes).map(|args| { + let Invoke { + message, + resolver, + acl, + } = invoke; + parse_args(function, message, acl, attributes).map(|args| { #[cfg(feature = "tracing")] quote! { use tracing::Instrument; @@ -318,8 +328,12 @@ fn body_blocking( invoke: &Invoke, attributes: &WrapperAttributes, ) -> syn::Result { - let Invoke { message, resolver } = invoke; - let args = parse_args(function, message, attributes)?; + let Invoke { + message, + resolver, + acl, + } = invoke; + let args = parse_args(function, message, acl, attributes)?; // the body of a `match` to early return any argument that wasn't successful in parsing. let match_body = quote!({ @@ -346,13 +360,14 @@ fn body_blocking( fn parse_args( function: &ItemFn, message: &Ident, + acl: &Ident, attributes: &WrapperAttributes, ) -> syn::Result> { function .sig .inputs .iter() - .map(|arg| parse_arg(&function.sig.ident, arg, message, attributes)) + .map(|arg| parse_arg(&function.sig.ident, arg, message, acl, attributes)) .collect() } @@ -361,6 +376,7 @@ fn parse_arg( command: &Ident, arg: &FnArg, message: &Ident, + acl: &Ident, attributes: &WrapperAttributes, ) -> syn::Result { // we have no use for self arguments @@ -412,6 +428,7 @@ fn parse_arg( name: stringify!(#command), key: #key, message: &#message, + acl: &#acl, } ))) } diff --git a/core/tauri-plugin/src/build/acl.rs b/core/tauri-plugin/src/build/acl.rs index 6d89fd663d7b..aa62bb41e9cb 100644 --- a/core/tauri-plugin/src/build/acl.rs +++ b/core/tauri-plugin/src/build/acl.rs @@ -32,7 +32,7 @@ pub struct DefaultPermission { /// Allowed or denied scoped when using this permission. #[serde(default)] - pub scopes: Scopes, + pub scope: Scopes, } #[derive(Debug, Deserialize)] diff --git a/core/tauri-utils/src/acl/mod.rs b/core/tauri-utils/src/acl/mod.rs index afe5eb734b84..5c47b8032072 100644 --- a/core/tauri-utils/src/acl/mod.rs +++ b/core/tauri-utils/src/acl/mod.rs @@ -64,7 +64,7 @@ pub struct InlinedPermission { /// Allowed or denied scoped when using this permission. #[serde(default)] - pub scopes: Scopes, + pub scope: Scopes, } /// A permission. diff --git a/core/tauri-utils/src/acl/resolved.rs b/core/tauri-utils/src/acl/resolved.rs index 9ea2b366c075..b3ca23e1ca64 100644 --- a/core/tauri-utils/src/acl/resolved.rs +++ b/core/tauri-utils/src/acl/resolved.rs @@ -2,15 +2,13 @@ use std::collections::BTreeMap; -use serde::{Deserialize, Serialize}; - use super::{ExecutionContext, Value}; /// A key for a scope, used to link a [`ResolvedCommand#structfield.scope`] to the store [`Resolved#structfield.scopes`]. pub type ScopeKey = usize; /// A resolved command permission. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ResolvedCommand { /// The list of window label patterns that is allowed to run this command. pub windows: Vec, @@ -18,16 +16,13 @@ pub struct ResolvedCommand { pub scope: ScopeKey, } -/// A resolved scope. Contains all scopes defined for a single command. -pub struct ResolvedScope -where - T: Serialize, - for<'de> T: Deserialize<'de>, -{ +/// A resolved scope. Merges all scopes defined for a single command. +#[derive(Debug)] +pub struct ResolvedScope { /// Allows something on the command. - pub allow: Vec, + pub allow: Vec, /// Denies something on the command. - pub deny: Vec, + pub deny: Vec, } /// A command key for the map of allowed and denied commands. @@ -47,7 +42,7 @@ pub struct Resolved { /// The commands that are denied. Map each command with its context to a [`ResolvedCommand`]. pub denied_commands: BTreeMap, /// The store of scopes referenced by a [`ResolvedCommand`]. - pub scopes: BTreeMap>, + pub scope: BTreeMap, } #[cfg(feature = "build")] @@ -88,7 +83,7 @@ mod build { } } - impl ToTokens for ResolvedScope { + impl ToTokens for ResolvedScope { fn to_tokens(&self, tokens: &mut TokenStream) { let allow = vec_lit(&self.allow, identity); let deny = vec_lit(&self.deny, identity); @@ -112,14 +107,14 @@ mod build { identity, ); - let scopes = map_lit( + let scope = map_lit( quote! { ::std::collections::BTreeMap }, - &self.scopes, + &self.scope, identity, identity, ); - literal_struct!(tokens, Resolved, allowed_commands, denied_commands, scopes) + literal_struct!(tokens, Resolved, allowed_commands, denied_commands, scope) } } } diff --git a/core/tauri-utils/src/acl/value.rs b/core/tauri-utils/src/acl/value.rs index 38b24763e2f1..df68ff990a8a 100644 --- a/core/tauri-utils/src/acl/value.rs +++ b/core/tauri-utils/src/acl/value.rs @@ -55,9 +55,9 @@ pub enum Value { impl Value { /// TODO: implement [`serde::Deserializer`] directly to avoid serializing then deserializing pub fn deserialize(&self) -> Option { - dbg!(toml::to_string(self)) + dbg!(serde_json::to_string(self)) .ok() - .and_then(|s| dbg!(toml::from_str(&s).ok())) + .and_then(|s| dbg!(serde_json::from_str(&s).ok())) } } @@ -111,7 +111,7 @@ mod build { impl ToTokens for Number { fn to_tokens(&self, tokens: &mut TokenStream) { - let prefix = quote! { ::tauri::utils::acl:::Number }; + let prefix = quote! { ::tauri::utils::acl::Number }; tokens.append_all(match self { Self::Int(i) => { @@ -126,7 +126,7 @@ mod build { impl ToTokens for Value { fn to_tokens(&self, tokens: &mut TokenStream) { - let prefix = quote! { ::tauri::acl::Value }; + let prefix = quote! { ::tauri::utils::acl::Value }; tokens.append_all(match self { Value::Bool(bool) => quote! { #prefix::Bool(#bool) }, @@ -137,10 +137,15 @@ mod build { } Value::List(vec) => { let items = vec_lit(vec, identity); - quote! { #prefix::Array(#items) } + quote! { #prefix::List(#items) } } Value::Map(map) => { - let map = map_lit(quote! { ::tauri::acl::Map }, map, str_lit, identity); + let map = map_lit( + quote! { ::std::collections::BTreeMap }, + map, + str_lit, + identity, + ); quote! { #prefix::Map(#map) } } }); diff --git a/core/tauri/src/command/authority.rs b/core/tauri/src/command/authority.rs index 9b9ff880fe26..d92e0c767573 100644 --- a/core/tauri/src/command/authority.rs +++ b/core/tauri/src/command/authority.rs @@ -4,16 +4,20 @@ use std::fmt::Debug; use serde::de::DeserializeOwned; use state::TypeMap; -use serde_json::Value; use tauri_utils::acl::{ - resolved::{CommandKey, Resolved, ResolvedCommand}, + resolved::{CommandKey, Resolved, ResolvedCommand, ResolvedScope, ScopeKey}, ExecutionContext, }; +use crate::{ipc::InvokeError, Runtime}; + +use super::{CommandArg, CommandItem}; + /// The runtime authority used to authorize IPC execution based on the Access Control List. pub struct RuntimeAuthority { allowed_commands: BTreeMap, denied_commands: BTreeMap, + scope_manager: ScopeManager, } impl RuntimeAuthority { @@ -21,45 +25,107 @@ impl RuntimeAuthority { Self { allowed_commands: acl.allowed_commands, denied_commands: acl.denied_commands, + scope_manager: ScopeManager { + raw: acl.scope, + cache: ::new(), + }, } } - /// Checks if the given IPC execution is allowed. - pub fn is_allowed(&self, command: &str, window: &String, context: ExecutionContext) -> bool { + /// Checks if the given IPC execution is allowed and returns the [`ResolvedCommand`] if it is. + pub fn resolve_access( + &self, + command: &str, + window: &String, + context: ExecutionContext, + ) -> Option<&ResolvedCommand> { let key = CommandKey { name: command.into(), context, }; if self.denied_commands.contains_key(&key) { - false - } else if let Some(allowed) = self.allowed_commands.get(&key) { - allowed.windows.contains(window) + None } else { - false + self + .allowed_commands + .get(&key) + .filter(|allowed| allowed.windows.contains(window)) } } } -#[allow(dead_code)] +#[derive(Debug)] +struct CommandScope { + allow: Vec, + deny: Vec, +} + +/// Access scope for a command that can be retrieved directly in the command function. +#[derive(Debug)] +pub struct AccessScope<'a, T: Debug + DeserializeOwned + Send + Sync + 'static>( + &'a CommandScope, +); + +impl<'a, T: Debug + DeserializeOwned + Send + Sync + 'static> AccessScope<'a, T> { + /// What this access scope allows. + pub fn allows(&self) -> &Vec { + &self.0.allow + } + + /// What this access scope denies. + pub fn denies(&self) -> &Vec { + &self.0.deny + } +} + +impl<'a, R: Runtime, T: Debug + DeserializeOwned + Send + Sync + 'static> CommandArg<'a, R> + for AccessScope<'a, T> +{ + /// Grabs the [`Window`] from the [`CommandItem`] and returns the associated [`Scope`]. + fn from_command(command: CommandItem<'a, R>) -> Result { + command + .acl + .as_ref() + .and_then(|resolved| { + command + .message + .window + .manager + .runtime_authority + .scope_manager + .get_typed(&resolved.scope) + .map(AccessScope) + }) + .ok_or_else(|| InvokeError::from_anyhow(anyhow::anyhow!("scope not found"))) + } +} + #[derive(Debug, Default)] pub struct ScopeManager { - raw: BTreeMap, + raw: BTreeMap, cache: TypeMap![Send + Sync], } -#[allow(dead_code)] impl ScopeManager { - pub fn get_typed( + fn get_typed( &self, - key: &str, - ) -> Option<&T> { + key: &ScopeKey, + ) -> Option<&CommandScope> { match self.cache.try_get() { cached @ Some(_) => cached, - None => match self - .raw - .get(key) - .and_then(|r| dbg!(serde_json::from_value::(dbg!(r.clone()))).ok()) - { + None => match self.raw.get(key).map(|r| { + let mut allow: Vec = Vec::new(); + let mut deny: Vec = Vec::new(); + + for allowed in &r.allow { + allow.push(allowed.deserialize().unwrap()); + } + for denied in &r.deny { + deny.push(denied.deserialize().unwrap()); + } + + CommandScope { allow, deny } + }) { None => None, Some(value) => { let _ = self.cache.set(value); diff --git a/core/tauri/src/command/mod.rs b/core/tauri/src/command/mod.rs index e009691c2657..0e1f67dd9bfd 100644 --- a/core/tauri/src/command/mod.rs +++ b/core/tauri/src/command/mod.rs @@ -18,7 +18,8 @@ use serde::{ mod authority; -pub use authority::RuntimeAuthority; +pub use authority::{AccessScope, RuntimeAuthority}; +use tauri_utils::acl::resolved::ResolvedCommand; /// Represents a custom command. pub struct CommandItem<'a, R: Runtime> { @@ -30,6 +31,9 @@ pub struct CommandItem<'a, R: Runtime> { /// The [`InvokeMessage`] that was passed to this command. pub message: &'a InvokeMessage, + + /// The resolved ACL for this command. + pub acl: &'a Option, } /// Trait implemented by command arguments to derive a value from a [`CommandItem`]. diff --git a/core/tauri/src/ipc/mod.rs b/core/tauri/src/ipc/mod.rs index eb37295f959e..9f17d6c12fec 100644 --- a/core/tauri/src/ipc/mod.rs +++ b/core/tauri/src/ipc/mod.rs @@ -14,6 +14,7 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde_json::Value as JsonValue; pub use serialize_to_javascript::Options as SerializeOptions; use tauri_macros::default_runtime; +use tauri_utils::acl::resolved::ResolvedCommand; use crate::{ command::{CommandArg, CommandItem}, @@ -159,6 +160,9 @@ pub struct Invoke { /// The resolver of the message. pub resolver: InvokeResolver, + + /// Resolved ACL for this IPC invoke. + pub acl: Option, } /// Error response from an [`InvokeMessage`]. diff --git a/core/tauri/src/window/mod.rs b/core/tauri/src/window/mod.rs index 79afdda978f1..55f0cefa569a 100644 --- a/core/tauri/src/window/mod.rs +++ b/core/tauri/src/window/mod.rs @@ -2353,30 +2353,34 @@ impl Window { request.headers, ); + let resolved_acl = manager + .runtime_authority + .resolve_access( + &request.cmd, + &message.window.window.label, + if is_local { + ExecutionContext::Local + } else { + ExecutionContext::Remote { + domain: current_url + .domain() + .map(|d| d.to_string()) + .unwrap_or_default(), + } + }, + ) + .cloned(); + let mut invoke = Invoke { message, resolver: resolver.clone(), + acl: resolved_acl, }; if !is_local && scope.is_none() { invoke.resolver.reject(scope_not_found_error_message); } else if request.cmd.starts_with("plugin:") { - if request.cmd != crate::ipc::channel::FETCH_CHANNEL_DATA_COMMAND - && !manager.runtime_authority.is_allowed( - &request.cmd, - &invoke.message.window.window.label, - if is_local { - ExecutionContext::Local - } else { - ExecutionContext::Remote { - domain: current_url - .domain() - .map(|d| d.to_string()) - .unwrap_or_default(), - } - }, - ) - { + if request.cmd != crate::ipc::channel::FETCH_CHANNEL_DATA_COMMAND && invoke.acl.is_none() { invoke.resolver.reject("NOT ALLOWED"); return; } diff --git a/examples/api/src-tauri/capabilities/run-app.toml b/examples/api/src-tauri/capabilities/run-app.toml index 0a80917c748d..890ba9d7bd45 100644 --- a/examples/api/src-tauri/capabilities/run-app.toml +++ b/examples/api/src-tauri/capabilities/run-app.toml @@ -1,4 +1,4 @@ identifier = "run-app" description = "app capability" windows = ["main"] -permissions = ["sample:allow-ping"] +permissions = ["sample:allow-ping-scoped"] diff --git a/examples/api/src-tauri/tauri-plugin-sample/permissions/ping-scoped.toml b/examples/api/src-tauri/tauri-plugin-sample/permissions/ping-scoped.toml new file mode 100644 index 000000000000..7761c8b0763a --- /dev/null +++ b/examples/api/src-tauri/tauri-plugin-sample/permissions/ping-scoped.toml @@ -0,0 +1,6 @@ +[[permission]] +identifier = "allow-ping-scoped" +description = "This enables the ping command with a test scope." +commands.allow = ["ping"] +[permission.scope.allow] +path = "x" diff --git a/examples/api/src-tauri/tauri-plugin-sample/src/lib.rs b/examples/api/src-tauri/tauri-plugin-sample/src/lib.rs index 69e69b37b8fe..c3bf6cc3a34a 100644 --- a/examples/api/src-tauri/tauri-plugin-sample/src/lib.rs +++ b/examples/api/src-tauri/tauri-plugin-sample/src/lib.rs @@ -2,6 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT +use serde::Deserialize; +use std::path::PathBuf; use tauri::{ plugin::{Builder, TauriPlugin}, Manager, Runtime, @@ -35,11 +37,19 @@ impl> crate::SampleExt for T { } } +#[allow(dead_code)] +#[derive(Debug, Deserialize)] +struct PingScope { + path: PathBuf, +} + #[tauri::command] fn ping( app: tauri::AppHandle, value: Option, + scope: tauri::command::AccessScope, ) -> std::result::Result { + println!("{:?}", scope); app .sample() .ping(PingRequest { From 0922789e992f739c43844d454c28f6961576fed0 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Sat, 13 Jan 2024 14:16:50 -0300 Subject: [PATCH 20/69] fix tests [skip ci] --- core/tauri-codegen/src/context.rs | 26 ++++-- core/tauri/src/scope/ipc.rs | 141 +++++++++++++++++++++--------- core/tauri/src/test/mod.rs | 6 ++ 3 files changed, 125 insertions(+), 48 deletions(-) diff --git a/core/tauri-codegen/src/context.rs b/core/tauri-codegen/src/context.rs index 41e618562967..642158f8d234 100644 --- a/core/tauri-codegen/src/context.rs +++ b/core/tauri-codegen/src/context.rs @@ -381,15 +381,23 @@ pub fn context_codegen(data: ContextData) -> Result = - serde_json::from_str(&acl_file).expect("failed to parse plugin manifest map"); - - let capabilities_file = std::fs::read_to_string(out_dir.join(CAPABILITIES_FILE_NAME)) - .expect("failed to read capabilities"); - let capabilities: HashMap = - serde_json::from_str(&capabilities_file).expect("failed to parse capabilities"); + let acl_file_path = out_dir.join(PLUGIN_MANIFESTS_FILE_NAME); + let acl: HashMap = if acl_file_path.exists() { + let acl_file = + std::fs::read_to_string(acl_file_path).expect("failed to read plugin manifest map"); + serde_json::from_str(&acl_file).expect("failed to parse plugin manifest map") + } else { + Default::default() + }; + + let capabilities_file_path = out_dir.join(CAPABILITIES_FILE_NAME); + let capabilities: HashMap = 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") + } else { + Default::default() + }; let resolved_act = resolve_acl::resolve(acl, capabilities).expect("failed to resolve ACL"); diff --git a/core/tauri/src/scope/ipc.rs b/core/tauri/src/scope/ipc.rs index 363c257cdb8c..e147c5bcd041 100644 --- a/core/tauri/src/scope/ipc.rs +++ b/core/tauri/src/scope/ipc.rs @@ -166,18 +166,53 @@ impl Scope { #[cfg(test)] mod tests { + use tauri_utils::acl::{ + resolved::{CommandKey, ResolvedCommand}, + ExecutionContext, + }; + use super::RemoteDomainAccessScope; use crate::{ ipc::CallbackFn, - test::{assert_ipc_response, mock_app, MockRuntime}, + test::{assert_ipc_response, mock_builder, mock_context, noop_assets, MockRuntime}, window::InvokeRequest, App, Manager, Window, WindowBuilder, }; const PLUGIN_NAME: &str = "test"; - fn test_context(scopes: Vec) -> (App, Window) { - let app = mock_app(); + fn test_context( + request: &InvokeRequest, + scopes: Vec, + ) -> (App, Window) { + let mut ctx = mock_context(noop_assets()); + + ctx.resolved_acl.allowed_commands.insert( + CommandKey { + name: request.cmd.clone(), + context: ExecutionContext::Local, + }, + ResolvedCommand { + windows: vec!["main".into()], + scope: 0, + }, + ); + for scope in &scopes { + ctx.resolved_acl.allowed_commands.insert( + CommandKey { + name: request.cmd.clone(), + context: ExecutionContext::Remote { + domain: scope.domain.clone(), + }, + }, + ResolvedCommand { + windows: vec!["main".into()], + scope: 0, + }, + ); + } + + let app = mock_builder().build(ctx).unwrap(); let window = WindowBuilder::new(&app, "main", Default::default()) .build() .unwrap(); @@ -223,14 +258,18 @@ mod tests { #[test] fn scope_not_defined() { - let (_app, mut window) = test_context(vec![RemoteDomainAccessScope::new("app.tauri.app") - .add_window("other") - .add_plugin("path")]); + let request = path_is_absolute_request(); + let (_app, mut window) = test_context( + &request, + vec![RemoteDomainAccessScope::new("app.tauri.app") + .add_window("other") + .add_plugin("path")], + ); window.navigate("https://tauri.app".parse().unwrap()); assert_ipc_response( &window, - path_is_absolute_request(), + request, Err(crate::window::ipc_scope_not_found_error_message( "main", "https://tauri.app/", @@ -240,28 +279,37 @@ mod tests { #[test] fn scope_not_defined_for_window() { - let (_app, mut window) = test_context(vec![RemoteDomainAccessScope::new("tauri.app") - .add_window("second") - .add_plugin("path")]); + let request = path_is_absolute_request(); + let (_app, mut window) = test_context( + &request, + vec![RemoteDomainAccessScope::new("tauri.app") + .add_window("second") + .add_plugin("path")], + ); window.navigate("https://tauri.app".parse().unwrap()); assert_ipc_response( &window, - path_is_absolute_request(), + request, Err(crate::window::ipc_scope_window_error_message("main")), ); } #[test] fn scope_not_defined_for_url() { - let (_app, mut window) = test_context(vec![RemoteDomainAccessScope::new("github.com") - .add_window("main") - .add_plugin("path")]); + let request = path_is_absolute_request(); + + let (_app, mut window) = test_context( + &request, + vec![RemoteDomainAccessScope::new("github.com") + .add_window("main") + .add_plugin("path")], + ); window.navigate("https://tauri.app".parse().unwrap()); assert_ipc_response( &window, - path_is_absolute_request(), + request, Err(crate::window::ipc_scope_domain_error_message( "https://tauri.app/", )), @@ -270,14 +318,17 @@ mod tests { #[test] fn subdomain_is_not_allowed() { - let (_app, mut window) = test_context(vec![ - RemoteDomainAccessScope::new("tauri.app") - .add_window("main") - .add_plugin("path"), - RemoteDomainAccessScope::new("sub.tauri.app") - .add_window("main") - .add_plugin("path"), - ]); + let (_app, mut window) = test_context( + &path_is_absolute_request(), + vec![ + RemoteDomainAccessScope::new("tauri.app") + .add_window("main") + .add_plugin("path"), + RemoteDomainAccessScope::new("sub.tauri.app") + .add_window("main") + .add_plugin("path"), + ], + ); window.navigate("https://tauri.app".parse().unwrap()); assert_ipc_response(&window, path_is_absolute_request(), Ok(true)); @@ -308,52 +359,64 @@ mod tests { #[test] fn subpath_is_allowed() { - let (_app, mut window) = test_context(vec![RemoteDomainAccessScope::new("tauri.app") - .add_window("main") - .add_plugin("path")]); + let request = path_is_absolute_request(); + let (_app, mut window) = test_context( + &request, + vec![RemoteDomainAccessScope::new("tauri.app") + .add_window("main") + .add_plugin("path")], + ); window.navigate("https://tauri.app/inner/path".parse().unwrap()); - assert_ipc_response(&window, path_is_absolute_request(), Ok(true)); + assert_ipc_response(&window, request, Ok(true)); } #[test] fn tauri_api_not_allowed() { - let (_app, mut window) = test_context(vec![ - RemoteDomainAccessScope::new("tauri.app").add_window("main") - ]); + let request = path_is_absolute_request(); + let (_app, mut window) = test_context( + &request, + vec![RemoteDomainAccessScope::new("tauri.app").add_window("main")], + ); window.navigate("https://tauri.app".parse().unwrap()); assert_ipc_response( &window, - path_is_absolute_request(), + request, Err(crate::window::IPC_SCOPE_DOES_NOT_ALLOW), ); } #[test] fn plugin_allowed() { - let (_app, mut window) = test_context(vec![RemoteDomainAccessScope::new("tauri.app") - .add_window("main") - .add_plugin(PLUGIN_NAME)]); + let request = plugin_test_request(); + let (_app, mut window) = test_context( + &request, + vec![RemoteDomainAccessScope::new("tauri.app") + .add_window("main") + .add_plugin(PLUGIN_NAME)], + ); window.navigate("https://tauri.app".parse().unwrap()); assert_ipc_response( &window, - plugin_test_request(), + request, Err(format!("plugin {PLUGIN_NAME} not found")), ); } #[test] fn plugin_not_allowed() { - let (_app, mut window) = test_context(vec![ - RemoteDomainAccessScope::new("tauri.app").add_window("main") - ]); + let request = plugin_test_request(); + let (_app, mut window) = test_context( + &request, + vec![RemoteDomainAccessScope::new("tauri.app").add_window("main")], + ); window.navigate("https://tauri.app".parse().unwrap()); assert_ipc_response( &window, - plugin_test_request(), + request, Err(crate::window::IPC_SCOPE_DOES_NOT_ALLOW), ); } diff --git a/core/tauri/src/test/mod.rs b/core/tauri/src/test/mod.rs index 933b53c37849..4473704d574d 100644 --- a/core/tauri/src/test/mod.rs +++ b/core/tauri/src/test/mod.rs @@ -62,6 +62,7 @@ use crate::{ App, Builder, Context, Pattern, Window, }; use tauri_utils::{ + acl::resolved::Resolved, assets::{AssetKey, Assets, CspHash}, config::{Config, PatternKind, TauriConfig}, }; @@ -125,6 +126,11 @@ pub fn mock_context(assets: A) -> crate::Context { }, _info_plist: (), pattern: Pattern::Brownfield(std::marker::PhantomData), + resolved_acl: Resolved { + allowed_commands: Default::default(), + denied_commands: Default::default(), + scope: Default::default(), + }, } } From 72d32d9aff5782445b7c8106034b75bf75c80072 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Sun, 14 Jan 2024 09:01:47 -0300 Subject: [PATCH 21/69] global scope --- core/tauri-codegen/src/context/resolve_acl.rs | 65 +++++++---- core/tauri-utils/src/acl/resolved.rs | 21 +++- core/tauri/src/command/authority.rs | 105 ++++++++++++++---- core/tauri/src/command/mod.rs | 2 +- core/tauri/src/test/mod.rs | 3 +- .../api/src-tauri/capabilities/run-app.toml | 2 +- .../permissions/global-scope.toml | 5 + .../src-tauri/tauri-plugin-sample/src/lib.rs | 6 +- 8 files changed, 155 insertions(+), 54 deletions(-) create mode 100644 examples/api/src-tauri/tauri-plugin-sample/permissions/global-scope.toml diff --git a/core/tauri-codegen/src/context/resolve_acl.rs b/core/tauri-codegen/src/context/resolve_acl.rs index 7c1c905f68d4..a7479c216f8c 100644 --- a/core/tauri-codegen/src/context/resolve_acl.rs +++ b/core/tauri-codegen/src/context/resolve_acl.rs @@ -29,7 +29,8 @@ pub fn resolve( let mut denied_commands = HashMap::new(); let mut current_scope_id = 0; - let mut scopes = HashMap::new(); + let mut command_scopes = HashMap::new(); + let mut global_scope = Vec::new(); // resolve commands for capability in capabilities.values() { @@ -40,25 +41,31 @@ pub fn resolve( let permissions = get_permissions(plugin_name, permission_name, &acl)?; for permission in permissions { - current_scope_id += 1; - scopes.insert(current_scope_id, permission.inner.scope.clone()); - - for allowed_command in &permission.inner.commands.allow { - resolve_command( - &mut allowed_commands, - format!("plugin:{plugin_name}|{allowed_command}"), - capability, - current_scope_id, - ); - } - - for denied_command in &permission.inner.commands.deny { - resolve_command( - &mut denied_commands, - format!("plugin:{plugin_name}|{denied_command}"), - capability, - current_scope_id, - ); + if permission.inner.commands.allow.is_empty() && permission.inner.commands.deny.is_empty() + { + // global scope + global_scope.push(permission.inner.scope.clone()); + } else { + current_scope_id += 1; + command_scopes.insert(current_scope_id, permission.inner.scope.clone()); + + for allowed_command in &permission.inner.commands.allow { + resolve_command( + &mut allowed_commands, + format!("plugin:{plugin_name}|{allowed_command}"), + capability, + current_scope_id, + ); + } + + for denied_command in &permission.inner.commands.deny { + resolve_command( + &mut denied_commands, + format!("plugin:{plugin_name}|{denied_command}"), + capability, + current_scope_id, + ); + } } } } @@ -81,18 +88,29 @@ pub fn resolve( allow: allowed .scope .iter() - .flat_map(|s| scopes.get(s).unwrap().allow.clone()) + .flat_map(|s| command_scopes.get(s).unwrap().allow.clone()) .collect(), deny: allowed .scope .iter() - .flat_map(|s| scopes.get(s).unwrap().deny.clone()) + .flat_map(|s| command_scopes.get(s).unwrap().deny.clone()) .collect(), }; resolved_scopes.insert(hash, resolved_scope); } + let global_scope = ResolvedScope { + allow: global_scope + .iter_mut() + .flat_map(|s| s.allow.take()) + .collect(), + deny: global_scope + .iter_mut() + .flat_map(|s| s.deny.take()) + .collect(), + }; + let resolved = Resolved { allowed_commands: allowed_commands .into_iter() @@ -118,7 +136,8 @@ pub fn resolve( ) }) .collect(), - scope: resolved_scopes, + command_scope: resolved_scopes, + global_scope, }; Ok(resolved) diff --git a/core/tauri-utils/src/acl/resolved.rs b/core/tauri-utils/src/acl/resolved.rs index b3ca23e1ca64..90d134f2ab7a 100644 --- a/core/tauri-utils/src/acl/resolved.rs +++ b/core/tauri-utils/src/acl/resolved.rs @@ -17,7 +17,7 @@ pub struct ResolvedCommand { } /// A resolved scope. Merges all scopes defined for a single command. -#[derive(Debug)] +#[derive(Debug, Default)] pub struct ResolvedScope { /// Allows something on the command. pub allow: Vec, @@ -42,7 +42,9 @@ pub struct Resolved { /// The commands that are denied. Map each command with its context to a [`ResolvedCommand`]. pub denied_commands: BTreeMap, /// The store of scopes referenced by a [`ResolvedCommand`]. - pub scope: BTreeMap, + pub command_scope: BTreeMap, + /// The global scope. + pub global_scope: ResolvedScope, } #[cfg(feature = "build")] @@ -107,14 +109,23 @@ mod build { identity, ); - let scope = map_lit( + let command_scope = map_lit( quote! { ::std::collections::BTreeMap }, - &self.scope, + &self.command_scope, identity, identity, ); - literal_struct!(tokens, Resolved, allowed_commands, denied_commands, scope) + let global_scope = &self.global_scope; + + literal_struct!( + tokens, + Resolved, + allowed_commands, + denied_commands, + command_scope, + global_scope + ) } } } diff --git a/core/tauri/src/command/authority.rs b/core/tauri/src/command/authority.rs index d92e0c767573..b5e33ff91173 100644 --- a/core/tauri/src/command/authority.rs +++ b/core/tauri/src/command/authority.rs @@ -22,12 +22,19 @@ pub struct RuntimeAuthority { impl RuntimeAuthority { pub(crate) fn new(acl: Resolved) -> Self { + let command_cache = acl + .command_scope + .keys() + .map(|key| (*key, ::new())) + .collect(); Self { allowed_commands: acl.allowed_commands, denied_commands: acl.denied_commands, scope_manager: ScopeManager { - raw: acl.scope, - cache: ::new(), + command_scope: acl.command_scope, + global_scope: acl.global_scope, + command_cache, + global_scope_cache: Default::default(), }, } } @@ -55,18 +62,16 @@ impl RuntimeAuthority { } #[derive(Debug)] -struct CommandScope { +struct ScopeValue { allow: Vec, deny: Vec, } /// Access scope for a command that can be retrieved directly in the command function. #[derive(Debug)] -pub struct AccessScope<'a, T: Debug + DeserializeOwned + Send + Sync + 'static>( - &'a CommandScope, -); +pub struct CommandScope<'a, T: Debug + DeserializeOwned + Send + Sync + 'static>(&'a ScopeValue); -impl<'a, T: Debug + DeserializeOwned + Send + Sync + 'static> AccessScope<'a, T> { +impl<'a, T: Debug + DeserializeOwned + Send + Sync + 'static> CommandScope<'a, T> { /// What this access scope allows. pub fn allows(&self) -> &Vec { &self.0.allow @@ -79,9 +84,9 @@ impl<'a, T: Debug + DeserializeOwned + Send + Sync + 'static> AccessScope<'a, T> } impl<'a, R: Runtime, T: Debug + DeserializeOwned + Send + Sync + 'static> CommandArg<'a, R> - for AccessScope<'a, T> + for CommandScope<'a, T> { - /// Grabs the [`Window`] from the [`CommandItem`] and returns the associated [`Scope`]. + /// Grabs the [`ResolvedScope`] from the [`CommandItem`] and returns the associated [`CommandScope`]. fn from_command(command: CommandItem<'a, R>) -> Result { command .acl @@ -93,27 +98,85 @@ impl<'a, R: Runtime, T: Debug + DeserializeOwned + Send + Sync + 'static> Comman .manager .runtime_authority .scope_manager - .get_typed(&resolved.scope) - .map(AccessScope) + .get_command_scope_typed(&resolved.scope) + .map(CommandScope) }) .ok_or_else(|| InvokeError::from_anyhow(anyhow::anyhow!("scope not found"))) } } -#[derive(Debug, Default)] +/// Global access scope that can be retrieved directly in the command function. +#[derive(Debug)] +pub struct GlobalScope<'a, T: Debug + DeserializeOwned + Send + Sync + 'static>(&'a ScopeValue); + +impl<'a, T: Debug + DeserializeOwned + Send + Sync + 'static> GlobalScope<'a, T> { + /// What this access scope allows. + pub fn allows(&self) -> &Vec { + &self.0.allow + } + + /// What this access scope denies. + pub fn denies(&self) -> &Vec { + &self.0.deny + } +} + +impl<'a, R: Runtime, T: Debug + DeserializeOwned + Send + Sync + 'static> CommandArg<'a, R> + for GlobalScope<'a, T> +{ + /// Grabs the [`ResolvedScope`] from the [`CommandItem`] and returns the associated [`GlobalScope`]. + fn from_command(command: CommandItem<'a, R>) -> Result { + let scope = command + .message + .window + .manager + .runtime_authority + .scope_manager + .get_global_scope_typed(); + Ok(GlobalScope(scope)) + } +} + +#[derive(Debug)] pub struct ScopeManager { - raw: BTreeMap, - cache: TypeMap![Send + Sync], + command_scope: BTreeMap, + global_scope: ResolvedScope, + command_cache: BTreeMap, + global_scope_cache: TypeMap![Send + Sync], } impl ScopeManager { - fn get_typed( + fn get_global_scope_typed( + &self, + ) -> &ScopeValue { + match self.global_scope_cache.try_get() { + Some(cached) => cached, + None => { + let mut allow: Vec = Vec::new(); + let mut deny: Vec = Vec::new(); + + for allowed in &self.global_scope.allow { + allow.push(allowed.deserialize().unwrap()); + } + for denied in &self.global_scope.deny { + deny.push(denied.deserialize().unwrap()); + } + + let scope = ScopeValue { allow, deny }; + let _ = self.global_scope_cache.set(scope); + self.global_scope_cache.get() + } + } + } + + fn get_command_scope_typed( &self, key: &ScopeKey, - ) -> Option<&CommandScope> { - match self.cache.try_get() { + ) -> Option<&ScopeValue> { + let cache = self.command_cache.get(key).unwrap(); + match cache.try_get() { cached @ Some(_) => cached, - None => match self.raw.get(key).map(|r| { + None => match self.command_scope.get(key).map(|r| { let mut allow: Vec = Vec::new(); let mut deny: Vec = Vec::new(); @@ -124,12 +187,12 @@ impl ScopeManager { deny.push(denied.deserialize().unwrap()); } - CommandScope { allow, deny } + ScopeValue { allow, deny } }) { None => None, Some(value) => { - let _ = self.cache.set(value); - self.cache.try_get() + let _ = cache.set(value); + cache.try_get() } }, } diff --git a/core/tauri/src/command/mod.rs b/core/tauri/src/command/mod.rs index 0e1f67dd9bfd..8fae0dd60300 100644 --- a/core/tauri/src/command/mod.rs +++ b/core/tauri/src/command/mod.rs @@ -18,7 +18,7 @@ use serde::{ mod authority; -pub use authority::{AccessScope, RuntimeAuthority}; +pub use authority::{CommandScope, GlobalScope, RuntimeAuthority}; use tauri_utils::acl::resolved::ResolvedCommand; /// Represents a custom command. diff --git a/core/tauri/src/test/mod.rs b/core/tauri/src/test/mod.rs index 4473704d574d..9ed6b3466d8e 100644 --- a/core/tauri/src/test/mod.rs +++ b/core/tauri/src/test/mod.rs @@ -129,7 +129,8 @@ pub fn mock_context(assets: A) -> crate::Context { resolved_acl: Resolved { allowed_commands: Default::default(), denied_commands: Default::default(), - scope: Default::default(), + command_scope: Default::default(), + global_scope: Default::default(), }, } } diff --git a/examples/api/src-tauri/capabilities/run-app.toml b/examples/api/src-tauri/capabilities/run-app.toml index 890ba9d7bd45..ee1eef11917e 100644 --- a/examples/api/src-tauri/capabilities/run-app.toml +++ b/examples/api/src-tauri/capabilities/run-app.toml @@ -1,4 +1,4 @@ identifier = "run-app" description = "app capability" windows = ["main"] -permissions = ["sample:allow-ping-scoped"] +permissions = ["sample:allow-ping-scoped", "sample:global-scope"] diff --git a/examples/api/src-tauri/tauri-plugin-sample/permissions/global-scope.toml b/examples/api/src-tauri/tauri-plugin-sample/permissions/global-scope.toml new file mode 100644 index 000000000000..5189e15e8760 --- /dev/null +++ b/examples/api/src-tauri/tauri-plugin-sample/permissions/global-scope.toml @@ -0,0 +1,5 @@ +[[permission]] +identifier = "global-scope" +description = "This sets a global scope." +[permission.scope.allow] +path = "global" diff --git a/examples/api/src-tauri/tauri-plugin-sample/src/lib.rs b/examples/api/src-tauri/tauri-plugin-sample/src/lib.rs index c3bf6cc3a34a..0d97fe649aab 100644 --- a/examples/api/src-tauri/tauri-plugin-sample/src/lib.rs +++ b/examples/api/src-tauri/tauri-plugin-sample/src/lib.rs @@ -47,9 +47,11 @@ struct PingScope { fn ping( app: tauri::AppHandle, value: Option, - scope: tauri::command::AccessScope, + scope: tauri::command::CommandScope, + global_scope: tauri::command::GlobalScope, ) -> std::result::Result { - println!("{:?}", scope); + println!("local scope {:?}", scope); + println!("global scope {:?}", global_scope); app .sample() .ping(PingRequest { From 9c950b3e678948187f7238e1d476e9ee915956b2 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Sun, 14 Jan 2024 09:02:24 -0300 Subject: [PATCH 22/69] lint --- core/tauri-plugin/src/build/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/tauri-plugin/src/build/mod.rs b/core/tauri-plugin/src/build/mod.rs index f5075e6dfcd6..fa3f0f012d25 100644 --- a/core/tauri-plugin/src/build/mod.rs +++ b/core/tauri-plugin/src/build/mod.rs @@ -83,7 +83,7 @@ impl<'a> Builder<'a> { let commands_dir = &autogenerated.join("commands"); if !self.commands.is_empty() { - autogenerate_command_permissions(&commands_dir, self.commands); + autogenerate_command_permissions(commands_dir, self.commands); } acl::define_permissions("./permissions/**/*.*")?; @@ -101,7 +101,7 @@ fn autogenerate_command_permissions(path: &Path, commands: &[&str]) { } for command in commands { - let slugified_command = command.replace("_", "-"); + let slugified_command = command.replace('_', "-"); let toml = format!( r###"# Automatically generated - DO NOT EDIT! @@ -123,7 +123,7 @@ commands.deny = [ ); std::fs::write(path.join(format!("{command}.toml")), toml) - .expect(&format!("unable to autogenerate ${command}.toml")); + .unwrap_or_else(|_| panic!("unable to autogenerate ${command}.toml")); } } From 1e2c44bf8501ef60db6ce9f057fe9a8a079852b5 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Sun, 14 Jan 2024 09:06:34 -0300 Subject: [PATCH 23/69] license headers [skip ci] --- core/tauri-build/src/acl.rs | 4 ++++ core/tauri-plugin/src/build/acl.rs | 4 ++++ core/tauri-plugin/src/build/mod.rs | 4 ++++ core/tauri-plugin/src/runtime.rs | 4 +++- core/tauri-utils/src/acl/capability.rs | 4 ++++ core/tauri-utils/src/acl/identifier.rs | 4 ++++ core/tauri-utils/src/acl/plugin.rs | 4 ++++ core/tauri-utils/src/acl/resolved.rs | 4 ++++ core/tauri-utils/src/acl/value.rs | 4 ++++ core/tauri-utils/src/tokens.rs | 4 ++++ core/tauri/src/command/authority.rs | 4 ++++ examples/plugins/tauri-plugin-example/build.rs | 4 ++++ examples/plugins/tauri-plugin-example/src/lib.rs | 4 ++++ 13 files changed, 51 insertions(+), 1 deletion(-) diff --git a/core/tauri-build/src/acl.rs b/core/tauri-build/src/acl.rs index 323a43b43002..b760dea28716 100644 --- a/core/tauri-build/src/acl.rs +++ b/core/tauri-build/src/acl.rs @@ -1,3 +1,7 @@ +// Copyright 2019-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + use std::collections::HashMap; use anyhow::{Context, Result}; diff --git a/core/tauri-plugin/src/build/acl.rs b/core/tauri-plugin/src/build/acl.rs index aa62bb41e9cb..e10548da3c86 100644 --- a/core/tauri-plugin/src/build/acl.rs +++ b/core/tauri-plugin/src/build/acl.rs @@ -1,3 +1,7 @@ +// Copyright 2019-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + use std::{collections::HashMap, env::vars_os, num::NonZeroU64, path::PathBuf}; use super::Error; diff --git a/core/tauri-plugin/src/build/mod.rs b/core/tauri-plugin/src/build/mod.rs index fa3f0f012d25..b39369d71746 100644 --- a/core/tauri-plugin/src/build/mod.rs +++ b/core/tauri-plugin/src/build/mod.rs @@ -1,3 +1,7 @@ +// Copyright 2019-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + use std::{fs::create_dir_all, path::Path}; use cargo_metadata::{Metadata, MetadataCommand}; diff --git a/core/tauri-plugin/src/runtime.rs b/core/tauri-plugin/src/runtime.rs index 8b137891791f..a056038571a5 100644 --- a/core/tauri-plugin/src/runtime.rs +++ b/core/tauri-plugin/src/runtime.rs @@ -1 +1,3 @@ - +// Copyright 2019-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT diff --git a/core/tauri-utils/src/acl/capability.rs b/core/tauri-utils/src/acl/capability.rs index fae5f78c4dbb..1daf495678e4 100644 --- a/core/tauri-utils/src/acl/capability.rs +++ b/core/tauri-utils/src/acl/capability.rs @@ -1,3 +1,7 @@ +// Copyright 2019-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + //! End-user abstraction for selecting permissions a window has access to. use crate::acl::Identifier; diff --git a/core/tauri-utils/src/acl/identifier.rs b/core/tauri-utils/src/acl/identifier.rs index 5c9996a2c6b2..d95ccb31cb18 100644 --- a/core/tauri-utils/src/acl/identifier.rs +++ b/core/tauri-utils/src/acl/identifier.rs @@ -1,3 +1,7 @@ +// Copyright 2019-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + //! Identifier for plugins. use serde::{Deserialize, Deserializer, Serialize, Serializer}; diff --git a/core/tauri-utils/src/acl/plugin.rs b/core/tauri-utils/src/acl/plugin.rs index beb6b7938609..e4291449f3a0 100644 --- a/core/tauri-utils/src/acl/plugin.rs +++ b/core/tauri-utils/src/acl/plugin.rs @@ -1,3 +1,7 @@ +// Copyright 2019-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + //! Plugin ACL types. use std::collections::HashMap; diff --git a/core/tauri-utils/src/acl/resolved.rs b/core/tauri-utils/src/acl/resolved.rs index 90d134f2ab7a..fc9d77957dd5 100644 --- a/core/tauri-utils/src/acl/resolved.rs +++ b/core/tauri-utils/src/acl/resolved.rs @@ -1,3 +1,7 @@ +// Copyright 2019-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + //! Resolved ACL for runtime usage. use std::collections::BTreeMap; diff --git a/core/tauri-utils/src/acl/value.rs b/core/tauri-utils/src/acl/value.rs index df68ff990a8a..956f1aab343b 100644 --- a/core/tauri-utils/src/acl/value.rs +++ b/core/tauri-utils/src/acl/value.rs @@ -1,3 +1,7 @@ +// Copyright 2019-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + //! A [`Value`] that is used instead of [`toml::Value`] or [`serde_json::Value`] //! to support both formats. diff --git a/core/tauri-utils/src/tokens.rs b/core/tauri-utils/src/tokens.rs index 1c01bf5082b6..81e9740d8c54 100644 --- a/core/tauri-utils/src/tokens.rs +++ b/core/tauri-utils/src/tokens.rs @@ -1,3 +1,7 @@ +// Copyright 2019-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + //! Utilities to implement [`ToTokens`] for a type. use std::path::Path; diff --git a/core/tauri/src/command/authority.rs b/core/tauri/src/command/authority.rs index b5e33ff91173..4eb959331211 100644 --- a/core/tauri/src/command/authority.rs +++ b/core/tauri/src/command/authority.rs @@ -1,3 +1,7 @@ +// Copyright 2019-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + use std::collections::BTreeMap; use std::fmt::Debug; diff --git a/examples/plugins/tauri-plugin-example/build.rs b/examples/plugins/tauri-plugin-example/build.rs index f33c1bfad2e2..d5d61c7b2591 100644 --- a/examples/plugins/tauri-plugin-example/build.rs +++ b/examples/plugins/tauri-plugin-example/build.rs @@ -1,3 +1,7 @@ +// Copyright 2019-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + const COMMANDS: &[&str] = &[]; fn main() { diff --git a/examples/plugins/tauri-plugin-example/src/lib.rs b/examples/plugins/tauri-plugin-example/src/lib.rs index 3b9acffd5adb..d23660817c7b 100644 --- a/examples/plugins/tauri-plugin-example/src/lib.rs +++ b/examples/plugins/tauri-plugin-example/src/lib.rs @@ -1,3 +1,7 @@ +// Copyright 2019-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + pub fn add(left: usize, right: usize) -> usize { left + right } From cc0d0163b707f86269573ecc7b2766e85a19c0a0 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Sun, 14 Jan 2024 09:08:17 -0300 Subject: [PATCH 24/69] skip canonicalize --- core/tauri-plugin/src/build/mod.rs | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/core/tauri-plugin/src/build/mod.rs b/core/tauri-plugin/src/build/mod.rs index b39369d71746..9da97d23a582 100644 --- a/core/tauri-plugin/src/build/mod.rs +++ b/core/tauri-plugin/src/build/mod.rs @@ -25,9 +25,6 @@ pub enum Error { )] LinksName, - #[error("CARGO_MANIFEST_DIR could not canonicalize")] - Manifest(std::io::Error), - #[error("failed to read file: {0}")] ReadFile(std::io::Error), @@ -137,13 +134,11 @@ fn build_var(key: &str) -> Result { } fn find_metadata() -> Result { - build_var("CARGO_MANIFEST_DIR") - .and_then(|p| std::fs::canonicalize(p).map_err(Error::Manifest)) - .and_then(|dir| { - MetadataCommand::new() - .current_dir(dir) - .no_deps() - .exec() - .map_err(Error::Metadata) - }) + build_var("CARGO_MANIFEST_DIR").and_then(|dir| { + MetadataCommand::new() + .current_dir(dir) + .no_deps() + .exec() + .map_err(Error::Metadata) + }) } From 2be498121b6bfcc42879d314f9cb31bd9916038b Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Sun, 14 Jan 2024 09:09:34 -0300 Subject: [PATCH 25/69] separate scope type in example --- examples/api/src-tauri/tauri-plugin-sample/src/lib.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/examples/api/src-tauri/tauri-plugin-sample/src/lib.rs b/examples/api/src-tauri/tauri-plugin-sample/src/lib.rs index 0d97fe649aab..72e5cd8096bc 100644 --- a/examples/api/src-tauri/tauri-plugin-sample/src/lib.rs +++ b/examples/api/src-tauri/tauri-plugin-sample/src/lib.rs @@ -43,12 +43,18 @@ struct PingScope { path: PathBuf, } +#[allow(dead_code)] +#[derive(Debug, Deserialize)] +struct SampleScope { + path: PathBuf, +} + #[tauri::command] fn ping( app: tauri::AppHandle, value: Option, scope: tauri::command::CommandScope, - global_scope: tauri::command::GlobalScope, + global_scope: tauri::command::GlobalScope, ) -> std::result::Result { println!("local scope {:?}", scope); println!("global scope {:?}", global_scope); From 609fcfb611bf1958db94c34a29799c345240d196 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Mon, 15 Jan 2024 08:25:35 -0300 Subject: [PATCH 26/69] remove inlinedpermission struct [skip ci] --- core/tauri-build/src/acl.rs | 18 +++++++----------- core/tauri-codegen/src/context/resolve_acl.rs | 11 +++++------ core/tauri-utils/src/acl/mod.rs | 10 +--------- 3 files changed, 13 insertions(+), 26 deletions(-) diff --git a/core/tauri-build/src/acl.rs b/core/tauri-build/src/acl.rs index b760dea28716..82bdb173710a 100644 --- a/core/tauri-build/src/acl.rs +++ b/core/tauri-build/src/acl.rs @@ -6,9 +6,7 @@ use std::collections::HashMap; use anyhow::{Context, Result}; use serde::Deserialize; -use tauri_utils::acl::{ - capability::Capability, plugin::Manifest, InlinedPermission, Permission, PermissionSet, -}; +use tauri_utils::acl::{capability::Capability, plugin::Manifest, Permission, PermissionSet}; #[derive(Deserialize)] #[serde(untagged)] @@ -61,13 +59,11 @@ pub(crate) fn get_plugin_manifests() -> Result> { for permission_file in permission_files { if let Some(default) = permission_file.default { manifest.default_permission.replace(Permission { - inner: InlinedPermission { - identifier: "default".into(), - version: default.version, - description: default.description, - commands: default.commands, - scope: default.scope, - }, + identifier: "default".into(), + version: default.version, + description: default.description, + commands: default.commands, + scope: default.scope, }); } @@ -75,7 +71,7 @@ pub(crate) fn get_plugin_manifests() -> Result> { manifest.permissions.extend( permissions .into_iter() - .map(|p| (p.inner.identifier.clone(), p)) + .map(|p| (p.identifier.clone(), p)) .collect::>(), ); } diff --git a/core/tauri-codegen/src/context/resolve_acl.rs b/core/tauri-codegen/src/context/resolve_acl.rs index a7479c216f8c..7899029d3ce5 100644 --- a/core/tauri-codegen/src/context/resolve_acl.rs +++ b/core/tauri-codegen/src/context/resolve_acl.rs @@ -41,15 +41,14 @@ pub fn resolve( let permissions = get_permissions(plugin_name, permission_name, &acl)?; for permission in permissions { - if permission.inner.commands.allow.is_empty() && permission.inner.commands.deny.is_empty() - { + if permission.commands.allow.is_empty() && permission.commands.deny.is_empty() { // global scope - global_scope.push(permission.inner.scope.clone()); + global_scope.push(permission.scope.clone()); } else { current_scope_id += 1; - command_scopes.insert(current_scope_id, permission.inner.scope.clone()); + command_scopes.insert(current_scope_id, permission.scope.clone()); - for allowed_command in &permission.inner.commands.allow { + for allowed_command in &permission.commands.allow { resolve_command( &mut allowed_commands, format!("plugin:{plugin_name}|{allowed_command}"), @@ -58,7 +57,7 @@ pub fn resolve( ); } - for denied_command in &permission.inner.commands.deny { + for denied_command in &permission.commands.deny { resolve_command( &mut denied_commands, format!("plugin:{plugin_name}|{denied_command}"), diff --git a/core/tauri-utils/src/acl/mod.rs b/core/tauri-utils/src/acl/mod.rs index 5c47b8032072..4fd3ce40635c 100644 --- a/core/tauri-utils/src/acl/mod.rs +++ b/core/tauri-utils/src/acl/mod.rs @@ -48,7 +48,7 @@ pub struct Scopes { /// /// If the scope is defined it can be used to fine grain control the access of individual or multiple commands. #[derive(Debug, Serialize, Deserialize)] -pub struct InlinedPermission { +pub struct Permission { /// The version of the permission. pub version: Option, @@ -67,14 +67,6 @@ pub struct InlinedPermission { pub scope: Scopes, } -/// A permission. -#[derive(Debug, Serialize, Deserialize)] -pub struct Permission { - /// Permission data. - #[serde(flatten)] - pub inner: InlinedPermission, -} - /// A set of direct permissions grouped together under a new name. #[derive(Debug, Serialize, Deserialize)] pub struct PermissionSet { From eba00d6539882ab284468d00fc24458f55ee8cae Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Mon, 15 Jan 2024 08:51:32 -0300 Subject: [PATCH 27/69] permission file schema --- core/tauri-build/src/acl.rs | 49 +++++++++--------- core/tauri-plugin/Cargo.toml | 19 +++++-- core/tauri-plugin/src/build/acl.rs | 50 ++++++++++++++++--- core/tauri-plugin/src/build/mod.rs | 31 +++++++++--- core/tauri-utils/src/acl/mod.rs | 4 ++ core/tauri-utils/src/acl/value.rs | 2 + examples/api/src-tauri/Cargo.lock | 44 ++++++++++++++++ .../permissions/.gitignore | 1 + .../autogenerated/commands/ping.toml | 10 ++-- .../permissions/global-scope.toml | 2 + .../permissions/ping-scoped.toml | 2 + .../permissions/.gitignore | 1 + .../permissions/home-config.toml | 2 + .../permissions/home-dir.toml | 4 +- .../tauri-plugin-example/permissions/set.toml | 11 ++-- 15 files changed, 175 insertions(+), 57 deletions(-) create mode 100644 examples/api/src-tauri/tauri-plugin-sample/permissions/.gitignore create mode 100644 examples/plugins/tauri-plugin-example/permissions/.gitignore diff --git a/core/tauri-build/src/acl.rs b/core/tauri-build/src/acl.rs index 82bdb173710a..e58c568ce5b3 100644 --- a/core/tauri-build/src/acl.rs +++ b/core/tauri-build/src/acl.rs @@ -67,31 +67,30 @@ pub(crate) fn get_plugin_manifests() -> Result> { }); } - if let Some(permissions) = permission_file.permission { - manifest.permissions.extend( - permissions - .into_iter() - .map(|p| (p.identifier.clone(), p)) - .collect::>(), - ); - } - if let Some(sets) = permission_file.set { - manifest.permission_sets.extend( - sets - .into_iter() - .map(|set| { - ( - set.identifier.clone(), - PermissionSet { - identifier: set.identifier, - description: set.description, - permissions: set.permissions, - }, - ) - }) - .collect::>(), - ); - } + manifest.permissions.extend( + permission_file + .permission + .into_iter() + .map(|p| (p.identifier.clone(), p)) + .collect::>(), + ); + + manifest.permission_sets.extend( + permission_file + .set + .into_iter() + .map(|set| { + ( + set.identifier.clone(), + PermissionSet { + identifier: set.identifier, + description: set.description, + permissions: set.permissions, + }, + ) + }) + .collect::>(), + ); } processed.insert(plugin_name, manifest); diff --git a/core/tauri-plugin/Cargo.toml b/core/tauri-plugin/Cargo.toml index 1155ed1570c5..47cb68dea874 100644 --- a/core/tauri-plugin/Cargo.toml +++ b/core/tauri-plugin/Cargo.toml @@ -10,18 +10,29 @@ edition = { workspace = true } rust-version = { workspace = true } [features] -build = ["dep:serde", "dep:cargo_metadata", "dep:thiserror", "dep:serde_json", "dep:glob", "dep:toml"] +build = [ + "dep:serde", + "dep:cargo_metadata", + "dep:thiserror", + "dep:serde_json", + "dep:glob", + "dep:toml", + "dep:schemars", +] [dependencies] serde = { version = "1", optional = true } thiserror = { version = "1", optional = true } cargo_metadata = { version = "0.18", optional = true } -tauri-utils = { version = "2.0.0-alpha.12", default-features = false, path = "../tauri-utils" } +tauri-utils = { version = "2.0.0-alpha.12", default-features = false, path = "../tauri-utils", features = [ + "schema", +] } serde_json = { version = "1", optional = true } glob = { version = "0.3", optional = true } toml = { version = "0.8", optional = true } +schemars = { version = "0.8", optional = true } [package.metadata.docs.rs] features = ["build", "runtime"] -rustc-args = [ "--cfg", "docsrs" ] -rustdoc-args = [ "--cfg", "docsrs" ] +rustc-args = ["--cfg", "docsrs"] +rustdoc-args = ["--cfg", "docsrs"] diff --git a/core/tauri-plugin/src/build/acl.rs b/core/tauri-plugin/src/build/acl.rs index e10548da3c86..f1ba543e898c 100644 --- a/core/tauri-plugin/src/build/acl.rs +++ b/core/tauri-plugin/src/build/acl.rs @@ -2,15 +2,24 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -use std::{collections::HashMap, env::vars_os, num::NonZeroU64, path::PathBuf}; +use std::{ + collections::HashMap, + env::vars_os, + fs::File, + io::{BufWriter, Write}, + num::NonZeroU64, + path::PathBuf, +}; use super::Error; use serde::Deserialize; use tauri_utils::acl::{Commands, Permission, Scopes}; const PERMISSION_FILES_PATH_KEY: &str = "PERMISSION_FILES_PATH"; +const PERMISSION_FILE_EXTENSIONS: &[&str] = &["json", "toml"]; +pub(crate) const PERMISSION_SCHEMA_FILE_NAME: &str = ".schema.json"; -#[derive(Debug, Deserialize)] +#[derive(Debug, Deserialize, schemars::JsonSchema)] pub struct PermissionSet { /// A unique identifier for the permission. pub identifier: String, @@ -22,7 +31,10 @@ pub struct PermissionSet { pub permissions: Vec, } -#[derive(Debug, Deserialize)] +/// The default permission of the plugin. +/// +/// Works similarly to a permission with the "default" identifier. +#[derive(Debug, Deserialize, schemars::JsonSchema)] pub struct DefaultPermission { /// The version of the permission. pub version: Option, @@ -39,17 +51,33 @@ pub struct DefaultPermission { pub scope: Scopes, } -#[derive(Debug, Deserialize)] +/// Permission file that can define a default permission, a set of permissions or a list of inlined permissions. +#[derive(Debug, Deserialize, schemars::JsonSchema)] pub struct PermissionFile { pub default: Option, - pub set: Option>, - pub permission: Option>, + #[serde(default)] + pub set: Vec, + #[serde(default)] + pub permission: Vec, } pub(crate) fn define_permissions(pattern: &str) -> Result<(), Error> { let permission_files = glob::glob(pattern)? .flatten() .flat_map(|p| p.canonicalize()) + // filter extension + .filter(|p| { + p.extension() + .and_then(|e| e.to_str()) + .map(|e| PERMISSION_FILE_EXTENSIONS.contains(&e)) + .unwrap_or_default() + }) + // filter schema file + .filter(|p| { + p.file_name() + .map(|name| name != PERMISSION_SCHEMA_FILE_NAME) + .unwrap_or(true) + }) .collect::>(); for path in &permission_files { @@ -73,6 +101,16 @@ pub(crate) fn define_permissions(pattern: &str) -> Result<(), Error> { Ok(()) } +pub(crate) fn generate_schema() -> Result<(), Error> { + let schema = schemars::schema_for!(PermissionFile); + let schema_str = serde_json::to_string_pretty(&schema).unwrap(); + let out_path = PathBuf::from("permissions").join(PERMISSION_SCHEMA_FILE_NAME); + + let mut schema_file = BufWriter::new(File::create(out_path).map_err(Error::CreateFile)?); + write!(schema_file, "{schema_str}").map_err(Error::WriteFile)?; + Ok(()) +} + pub fn read_permissions() -> Result>, Error> { let mut permissions_map = HashMap::new(); diff --git a/core/tauri-plugin/src/build/mod.rs b/core/tauri-plugin/src/build/mod.rs index 9da97d23a582..f5e51a408124 100644 --- a/core/tauri-plugin/src/build/mod.rs +++ b/core/tauri-plugin/src/build/mod.rs @@ -2,7 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -use std::{fs::create_dir_all, path::Path}; +use std::{ + env::current_dir, + fs::create_dir_all, + path::{Path, PathBuf}, +}; use cargo_metadata::{Metadata, MetadataCommand}; use thiserror::Error; @@ -31,6 +35,9 @@ pub enum Error { #[error("failed to write file: {0}")] WriteFile(std::io::Error), + #[error("failed to create file: {0}")] + CreateFile(std::io::Error), + #[error("failed to execute: {0}")] Metadata(#[from] cargo_metadata::Error), @@ -88,6 +95,7 @@ impl<'a> Builder<'a> { } acl::define_permissions("./permissions/**/*.*")?; + acl::generate_schema()?; let metadata = find_metadata()?; println!("{metadata:#?}"); @@ -101,26 +109,33 @@ fn autogenerate_command_permissions(path: &Path, commands: &[&str]) { create_dir_all(path).expect("unable to create autogenerated commands dir"); } + let cwd = current_dir().unwrap(); + let components_len = path.strip_prefix(&cwd).unwrap_or(path).components().count(); + let schema_path = (1..components_len) + .map(|_| "..") + .collect::() + .join(acl::PERMISSION_SCHEMA_FILE_NAME); + for command in commands { let slugified_command = command.replace('_', "-"); let toml = format!( r###"# Automatically generated - DO NOT EDIT! +"$schema" = "{schema_path}" + [[permission]] identifier = "allow-{slugified_command}" description = "This enables the {command} command without any pre-configured scope." -commands.allow = [ - "{command}" -] +commands.allow = ["{command}"] [[permission]] identifier = "deny-{slugified_command}" description = "This denies the {command} command without any pre-configured scope." -commands.deny = [ - "{command}" -]"###, +commands.deny = ["{command}"] +"###, command = command, - slugified_command = slugified_command + slugified_command = slugified_command, + schema_path = schema_path.display() ); std::fs::write(path.join(format!("{command}.toml")), toml) diff --git a/core/tauri-utils/src/acl/mod.rs b/core/tauri-utils/src/acl/mod.rs index 4fd3ce40635c..0588050878e2 100644 --- a/core/tauri-utils/src/acl/mod.rs +++ b/core/tauri-utils/src/acl/mod.rs @@ -19,6 +19,7 @@ pub mod value; /// /// If two commands clash inside of `allow` and `deny`, it should be denied by default. #[derive(Debug, Default, Serialize, Deserialize)] +#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] pub struct Commands { /// Allowed command. #[serde(default)] @@ -35,6 +36,7 @@ pub struct Commands { /// /// The scope is passed to the command and handled/enforced by the command itself. #[derive(Debug, Default, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] pub struct Scopes { /// Data that defines what is allowed by the scope. pub allow: Option, @@ -48,6 +50,7 @@ pub struct Scopes { /// /// If the scope is defined it can be used to fine grain control the access of individual or multiple commands. #[derive(Debug, Serialize, Deserialize)] +#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] pub struct Permission { /// The version of the permission. pub version: Option, @@ -69,6 +72,7 @@ pub struct Permission { /// A set of direct permissions grouped together under a new name. #[derive(Debug, Serialize, Deserialize)] +#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] pub struct PermissionSet { /// A unique identifier for the permission. pub identifier: String, diff --git a/core/tauri-utils/src/acl/value.rs b/core/tauri-utils/src/acl/value.rs index 956f1aab343b..88908ecd3a4c 100644 --- a/core/tauri-utils/src/acl/value.rs +++ b/core/tauri-utils/src/acl/value.rs @@ -13,6 +13,7 @@ use serde::{Deserialize, Serialize}; /// A valid ACL number. #[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialOrd, PartialEq)] +#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] #[serde(untagged)] pub enum Number { /// Represents an [`i64`]. @@ -38,6 +39,7 @@ impl From for Number { /// All supported ACL values. #[derive(Debug, Serialize, Deserialize, Clone, PartialOrd, PartialEq)] +#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] #[serde(untagged)] pub enum Value { /// Represents a [`bool`]. diff --git a/examples/api/src-tauri/Cargo.lock b/examples/api/src-tauri/Cargo.lock index d13e5cac3b3e..859e151dbf1f 100644 --- a/examples/api/src-tauri/Cargo.lock +++ b/examples/api/src-tauri/Cargo.lock @@ -985,6 +985,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +[[package]] +name = "dyn-clone" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" + [[package]] name = "embed-resource" version = "2.4.0" @@ -2987,6 +2993,31 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "schemars" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", + "url", +] + +[[package]] +name = "schemars_derive" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 1.0.109", +] + [[package]] name = "scoped-tls" version = "1.0.1" @@ -3048,6 +3079,17 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "serde_derive_internals" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "serde_json" version = "1.0.107" @@ -3566,6 +3608,7 @@ version = "0.1.0" dependencies = [ "cargo_metadata", "glob", + "schemars", "serde", "serde_json", "tauri-utils", @@ -3653,6 +3696,7 @@ dependencies = [ "phf 0.11.2", "proc-macro2", "quote", + "schemars", "semver", "serde", "serde_json", diff --git a/examples/api/src-tauri/tauri-plugin-sample/permissions/.gitignore b/examples/api/src-tauri/tauri-plugin-sample/permissions/.gitignore new file mode 100644 index 000000000000..9fe3b17f12ec --- /dev/null +++ b/examples/api/src-tauri/tauri-plugin-sample/permissions/.gitignore @@ -0,0 +1 @@ +.schema.json diff --git a/examples/api/src-tauri/tauri-plugin-sample/permissions/autogenerated/commands/ping.toml b/examples/api/src-tauri/tauri-plugin-sample/permissions/autogenerated/commands/ping.toml index 069ae2db6df6..49bc18a05517 100644 --- a/examples/api/src-tauri/tauri-plugin-sample/permissions/autogenerated/commands/ping.toml +++ b/examples/api/src-tauri/tauri-plugin-sample/permissions/autogenerated/commands/ping.toml @@ -1,15 +1,13 @@ # Automatically generated - DO NOT EDIT! +"$schema" = "../../.schema.json" + [[permission]] identifier = "allow-ping" description = "This enables the ping command without any pre-configured scope." -commands.allow = [ - "ping" -] +commands.allow = ["ping"] [[permission]] identifier = "deny-ping" description = "This denies the ping command without any pre-configured scope." -commands.deny = [ - "ping" -] \ No newline at end of file +commands.deny = ["ping"] diff --git a/examples/api/src-tauri/tauri-plugin-sample/permissions/global-scope.toml b/examples/api/src-tauri/tauri-plugin-sample/permissions/global-scope.toml index 5189e15e8760..3f74adb92823 100644 --- a/examples/api/src-tauri/tauri-plugin-sample/permissions/global-scope.toml +++ b/examples/api/src-tauri/tauri-plugin-sample/permissions/global-scope.toml @@ -1,3 +1,5 @@ +"$schema" = ".schema.json" + [[permission]] identifier = "global-scope" description = "This sets a global scope." diff --git a/examples/api/src-tauri/tauri-plugin-sample/permissions/ping-scoped.toml b/examples/api/src-tauri/tauri-plugin-sample/permissions/ping-scoped.toml index 7761c8b0763a..a6b8a37dfaa9 100644 --- a/examples/api/src-tauri/tauri-plugin-sample/permissions/ping-scoped.toml +++ b/examples/api/src-tauri/tauri-plugin-sample/permissions/ping-scoped.toml @@ -1,3 +1,5 @@ +"$schema" = ".schema.json" + [[permission]] identifier = "allow-ping-scoped" description = "This enables the ping command with a test scope." diff --git a/examples/plugins/tauri-plugin-example/permissions/.gitignore b/examples/plugins/tauri-plugin-example/permissions/.gitignore new file mode 100644 index 000000000000..9fe3b17f12ec --- /dev/null +++ b/examples/plugins/tauri-plugin-example/permissions/.gitignore @@ -0,0 +1 @@ +.schema.json diff --git a/examples/plugins/tauri-plugin-example/permissions/home-config.toml b/examples/plugins/tauri-plugin-example/permissions/home-config.toml index 3d1bbf4dc89c..7e5e47061337 100644 --- a/examples/plugins/tauri-plugin-example/permissions/home-config.toml +++ b/examples/plugins/tauri-plugin-example/permissions/home-config.toml @@ -1,3 +1,5 @@ +"$schema" = ".schema.json" + [[permission]] version = 1 identifier = "deny-home-dir-config" diff --git a/examples/plugins/tauri-plugin-example/permissions/home-dir.toml b/examples/plugins/tauri-plugin-example/permissions/home-dir.toml index 2b3dc1992501..b9808725cb93 100644 --- a/examples/plugins/tauri-plugin-example/permissions/home-dir.toml +++ b/examples/plugins/tauri-plugin-example/permissions/home-dir.toml @@ -1,8 +1,10 @@ +"$schema" = ".schema.json" + [[permission]] version = 1 identifier = "allow-home-dir" description = "This allows read access to the complete $HOME folder." -commands.allow = [ "readDirectory", "readFile" ] +commands.allow = ["readDirectory", "readFile"] [[scope.allow]] path = "$HOME/**" diff --git a/examples/plugins/tauri-plugin-example/permissions/set.toml b/examples/plugins/tauri-plugin-example/permissions/set.toml index 75877ad0f421..58a8ed57a36e 100644 --- a/examples/plugins/tauri-plugin-example/permissions/set.toml +++ b/examples/plugins/tauri-plugin-example/permissions/set.toml @@ -1,3 +1,5 @@ +"$schema" = ".schema.json" + [default] description = "Default permissions granted" permissions = ["allow-home-read-only"] @@ -5,14 +7,9 @@ permissions = ["allow-home-read-only"] [[set]] identifier = "allow-full-homefolder-access" description = "This allows read and write access to the complete $HOME folder." -permissions = [ - "allow-home-read-only", - "allow-home-write-only" -] +permissions = ["allow-home-read-only", "allow-home-write-only"] [[set]] identifier = "deny-homefolder-config-access" description = "This denies access to the $HOME/.config folder." -permissions = [ - "deny-home-dir-config" -] +permissions = ["deny-home-dir-config"] From 781243e8abe34fcd5998a777d38e34760930f33d Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Mon, 15 Jan 2024 10:08:37 -0300 Subject: [PATCH 28/69] capabilities schema --- core/tauri-build/Cargo.toml | 1 + core/tauri-build/src/acl.rs | 110 +++++++++++++++++- core/tauri-build/src/lib.rs | 1 + core/tauri-plugin/src/build/mod.rs | 4 +- core/tauri-utils/src/acl/capability.rs | 2 + core/tauri-utils/src/acl/identifier.rs | 1 + examples/api/src-tauri/Cargo.lock | 1 + .../api/src-tauri/capabilities/.gitignore | 1 + .../api/src-tauri/capabilities/run-app.toml | 1 + .../autogenerated/commands/ping.toml | 4 +- .../permissions/global-scope.toml | 2 +- .../permissions/ping-scoped.toml | 2 +- .../permissions/home-config.toml | 2 +- .../permissions/home-dir.toml | 2 +- .../tauri-plugin-example/permissions/set.toml | 4 +- 15 files changed, 126 insertions(+), 12 deletions(-) create mode 100644 examples/api/src-tauri/capabilities/.gitignore diff --git a/core/tauri-build/Cargo.toml b/core/tauri-build/Cargo.toml index c6b84c921e21..5877ebb962bd 100644 --- a/core/tauri-build/Cargo.toml +++ b/core/tauri-build/Cargo.toml @@ -42,6 +42,7 @@ semver = "1" dirs-next = "2" glob = "0.3" toml = "0.8" +schemars = "0.8" [target."cfg(target_os = \"macos\")".dependencies] swift-rs = { version = "1.0.6", features = [ "build" ] } diff --git a/core/tauri-build/src/acl.rs b/core/tauri-build/src/acl.rs index e58c568ce5b3..ad30681620f8 100644 --- a/core/tauri-build/src/acl.rs +++ b/core/tauri-build/src/acl.rs @@ -2,12 +2,24 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -use std::collections::HashMap; +use std::{ + collections::HashMap, + fs::File, + io::{BufWriter, Write}, + path::PathBuf, +}; use anyhow::{Context, Result}; +use schemars::{ + gen::SchemaGenerator, + schema::{InstanceType, Metadata, RootSchema, Schema, SchemaObject, SubschemaValidation}, +}; use serde::Deserialize; use tauri_utils::acl::{capability::Capability, plugin::Manifest, Permission, PermissionSet}; +const CAPABILITY_FILE_EXTENSIONS: &[&str] = &["json", "toml"]; +const CAPABILITIES_SCHEMA_FILE_NAME: &str = ".schema.json"; + #[derive(Deserialize)] #[serde(untagged)] enum CapabilityFile { @@ -15,10 +27,104 @@ enum CapabilityFile { List { capabilities: Vec }, } +fn capabilities_schema(plugin_manifests: &HashMap) -> RootSchema { + let mut schema = SchemaGenerator::default().into_root_schema_for::(); + + let mut permission_schemas = Vec::new(); + for (plugin, manifest) in plugin_manifests { + for (set_id, set) in &manifest.permission_sets { + permission_schemas.push(Schema::Object(SchemaObject { + metadata: Some(Box::new(Metadata { + description: Some(format!("{plugin}:{set_id} -> {}", set.description)), + ..Default::default() + })), + instance_type: Some(InstanceType::String.into()), + enum_values: Some(vec![serde_json::Value::String(format!( + "{plugin}:{set_id}" + ))]), + ..Default::default() + })); + } + + if let Some(default) = &manifest.default_permission { + permission_schemas.push(Schema::Object(SchemaObject { + metadata: Some(Box::new(Metadata { + description: default + .description + .as_ref() + .map(|d| format!("{plugin}:default -> {d}")), + ..Default::default() + })), + instance_type: Some(InstanceType::String.into()), + enum_values: Some(vec![serde_json::Value::String(format!("{plugin}:default"))]), + ..Default::default() + })); + } + + for (permission_id, permission) in &manifest.permissions { + permission_schemas.push(Schema::Object(SchemaObject { + metadata: Some(Box::new(Metadata { + description: permission + .description + .as_ref() + .map(|d| format!("{plugin}:{permission_id} -> {d}")), + ..Default::default() + })), + instance_type: Some(InstanceType::String.into()), + enum_values: Some(vec![serde_json::Value::String(format!( + "{plugin}:{permission_id}" + ))]), + ..Default::default() + })); + } + } + + if let Some(Schema::Object(obj)) = schema.definitions.get_mut("Identifier") { + obj.object = None; + obj.instance_type = None; + obj.metadata.as_mut().map(|metadata| { + metadata + .description + .replace("Permission identifier".to_string()); + metadata + }); + obj.subschemas.replace(Box::new(SubschemaValidation { + one_of: Some(permission_schemas), + ..Default::default() + })); + } + + schema +} + +pub(crate) fn generate_schema(plugin_manifests: &HashMap) -> Result<()> { + let schema = capabilities_schema(plugin_manifests); + let schema_str = serde_json::to_string_pretty(&schema).unwrap(); + let out_path = PathBuf::from("capabilities").join(CAPABILITIES_SCHEMA_FILE_NAME); + + let mut schema_file = BufWriter::new(File::create(out_path)?); + write!(schema_file, "{schema_str}")?; + Ok(()) +} + pub fn parse_capabilities(capabilities_path_pattern: &str) -> Result> { let mut capabilities_map = HashMap::new(); - for path in glob::glob(capabilities_path_pattern)?.flatten() { + for path in glob::glob(capabilities_path_pattern)? + .flatten() // filter extension + .filter(|p| { + p.extension() + .and_then(|e| e.to_str()) + .map(|e| CAPABILITY_FILE_EXTENSIONS.contains(&e)) + .unwrap_or_default() + }) + // filter schema file + .filter(|p| { + p.file_name() + .map(|name| name != CAPABILITIES_SCHEMA_FILE_NAME) + .unwrap_or(true) + }) + { println!("cargo:rerun-if-changed={}", path.display()); let capability_file = std::fs::read_to_string(&path)?; diff --git a/core/tauri-build/src/lib.rs b/core/tauri-build/src/lib.rs index 581babb92851..4f6170e49748 100644 --- a/core/tauri-build/src/lib.rs +++ b/core/tauri-build/src/lib.rs @@ -466,6 +466,7 @@ pub fn try_build(attributes: Attributes) -> Result<()> { } else { acl::parse_capabilities("./capabilities/**/*")? }; + acl::generate_schema(&plugin_manifests)?; acl::validate_capabilities(&plugin_manifests, &capabilities)?; diff --git a/core/tauri-plugin/src/build/mod.rs b/core/tauri-plugin/src/build/mod.rs index f5e51a408124..f54374972273 100644 --- a/core/tauri-plugin/src/build/mod.rs +++ b/core/tauri-plugin/src/build/mod.rs @@ -125,12 +125,12 @@ fn autogenerate_command_permissions(path: &Path, commands: &[&str]) { [[permission]] identifier = "allow-{slugified_command}" -description = "This enables the {command} command without any pre-configured scope." +description = "Enables the {command} command without any pre-configured scope." commands.allow = ["{command}"] [[permission]] identifier = "deny-{slugified_command}" -description = "This denies the {command} command without any pre-configured scope." +description = "Denies the {command} command without any pre-configured scope." commands.deny = ["{command}"] "###, command = command, diff --git a/core/tauri-utils/src/acl/capability.rs b/core/tauri-utils/src/acl/capability.rs index 1daf495678e4..fe037c5c03ee 100644 --- a/core/tauri-utils/src/acl/capability.rs +++ b/core/tauri-utils/src/acl/capability.rs @@ -21,6 +21,7 @@ pub struct CapabilitySet { /// 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)] +#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] pub struct Capability { /// Identifier of the capability. pub identifier: String, @@ -40,6 +41,7 @@ pub struct Capability { /// Context of the capability. #[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] pub enum CapabilityContext { /// Capability refers to local URL usage. #[default] diff --git a/core/tauri-utils/src/acl/identifier.rs b/core/tauri-utils/src/acl/identifier.rs index d95ccb31cb18..75c1d937ac20 100644 --- a/core/tauri-utils/src/acl/identifier.rs +++ b/core/tauri-utils/src/acl/identifier.rs @@ -18,6 +18,7 @@ const MAX_LEN_IDENTIFIER: usize = MAX_LEN_PREFIX + 1 + MAX_LEN_BASE; /// Plugin identifier. #[derive(Debug, Clone)] +#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] pub struct Identifier { inner: String, separator: Option, diff --git a/examples/api/src-tauri/Cargo.lock b/examples/api/src-tauri/Cargo.lock index 859e151dbf1f..e24bd903dbfc 100644 --- a/examples/api/src-tauri/Cargo.lock +++ b/examples/api/src-tauri/Cargo.lock @@ -3554,6 +3554,7 @@ dependencies = [ "json-patch", "plist", "quote", + "schemars", "semver", "serde", "serde_json", diff --git a/examples/api/src-tauri/capabilities/.gitignore b/examples/api/src-tauri/capabilities/.gitignore new file mode 100644 index 000000000000..9fe3b17f12ec --- /dev/null +++ b/examples/api/src-tauri/capabilities/.gitignore @@ -0,0 +1 @@ +.schema.json diff --git a/examples/api/src-tauri/capabilities/run-app.toml b/examples/api/src-tauri/capabilities/run-app.toml index ee1eef11917e..02ab69258f0b 100644 --- a/examples/api/src-tauri/capabilities/run-app.toml +++ b/examples/api/src-tauri/capabilities/run-app.toml @@ -1,3 +1,4 @@ +"$schema" = ".schema.json" identifier = "run-app" description = "app capability" windows = ["main"] diff --git a/examples/api/src-tauri/tauri-plugin-sample/permissions/autogenerated/commands/ping.toml b/examples/api/src-tauri/tauri-plugin-sample/permissions/autogenerated/commands/ping.toml index 49bc18a05517..7a6387ec69c5 100644 --- a/examples/api/src-tauri/tauri-plugin-sample/permissions/autogenerated/commands/ping.toml +++ b/examples/api/src-tauri/tauri-plugin-sample/permissions/autogenerated/commands/ping.toml @@ -4,10 +4,10 @@ [[permission]] identifier = "allow-ping" -description = "This enables the ping command without any pre-configured scope." +description = "Enables the ping command without any pre-configured scope." commands.allow = ["ping"] [[permission]] identifier = "deny-ping" -description = "This denies the ping command without any pre-configured scope." +description = "Denies the ping command without any pre-configured scope." commands.deny = ["ping"] diff --git a/examples/api/src-tauri/tauri-plugin-sample/permissions/global-scope.toml b/examples/api/src-tauri/tauri-plugin-sample/permissions/global-scope.toml index 3f74adb92823..4c0940550405 100644 --- a/examples/api/src-tauri/tauri-plugin-sample/permissions/global-scope.toml +++ b/examples/api/src-tauri/tauri-plugin-sample/permissions/global-scope.toml @@ -2,6 +2,6 @@ [[permission]] identifier = "global-scope" -description = "This sets a global scope." +description = "Sets a global scope." [permission.scope.allow] path = "global" diff --git a/examples/api/src-tauri/tauri-plugin-sample/permissions/ping-scoped.toml b/examples/api/src-tauri/tauri-plugin-sample/permissions/ping-scoped.toml index a6b8a37dfaa9..95b321df6c0a 100644 --- a/examples/api/src-tauri/tauri-plugin-sample/permissions/ping-scoped.toml +++ b/examples/api/src-tauri/tauri-plugin-sample/permissions/ping-scoped.toml @@ -2,7 +2,7 @@ [[permission]] identifier = "allow-ping-scoped" -description = "This enables the ping command with a test scope." +description = "Enables the ping command with a test scope." commands.allow = ["ping"] [permission.scope.allow] path = "x" diff --git a/examples/plugins/tauri-plugin-example/permissions/home-config.toml b/examples/plugins/tauri-plugin-example/permissions/home-config.toml index 7e5e47061337..52fff8928234 100644 --- a/examples/plugins/tauri-plugin-example/permissions/home-config.toml +++ b/examples/plugins/tauri-plugin-example/permissions/home-config.toml @@ -3,7 +3,7 @@ [[permission]] version = 1 identifier = "deny-home-dir-config" -description = "This denies read access to the complete $HOME folder." +description = "Denies read access to the complete $HOME folder." [[scope.deny]] path = "$HOME/.config" diff --git a/examples/plugins/tauri-plugin-example/permissions/home-dir.toml b/examples/plugins/tauri-plugin-example/permissions/home-dir.toml index b9808725cb93..1698107a14af 100644 --- a/examples/plugins/tauri-plugin-example/permissions/home-dir.toml +++ b/examples/plugins/tauri-plugin-example/permissions/home-dir.toml @@ -3,7 +3,7 @@ [[permission]] version = 1 identifier = "allow-home-dir" -description = "This allows read access to the complete $HOME folder." +description = "Allows read access to the complete $HOME folder." commands.allow = ["readDirectory", "readFile"] [[scope.allow]] diff --git a/examples/plugins/tauri-plugin-example/permissions/set.toml b/examples/plugins/tauri-plugin-example/permissions/set.toml index 58a8ed57a36e..9b36a41d165d 100644 --- a/examples/plugins/tauri-plugin-example/permissions/set.toml +++ b/examples/plugins/tauri-plugin-example/permissions/set.toml @@ -6,10 +6,10 @@ permissions = ["allow-home-read-only"] [[set]] identifier = "allow-full-homefolder-access" -description = "This allows read and write access to the complete $HOME folder." +description = "Allows read and write access to the complete $HOME folder." permissions = ["allow-home-read-only", "allow-home-write-only"] [[set]] identifier = "deny-homefolder-config-access" -description = "This denies access to the $HOME/.config folder." +description = "Denies access to the $HOME/.config folder." permissions = ["deny-home-dir-config"] From 6b7a0d0c46783bfe6a346c354039c4282ef16bb5 Mon Sep 17 00:00:00 2001 From: Chip Reed Date: Mon, 15 Jan 2024 09:29:32 -0800 Subject: [PATCH 29/69] move items from tauri-plugin to tauri-utils this allows tauri-plugin to depend on tauri directly again which will be used by the runtime feature as a superset to existing plugin traits --- core/tauri-build/Cargo.toml | 1 - core/tauri-build/src/acl.rs | 2 +- core/tauri-plugin/Cargo.toml | 3 +- core/tauri-plugin/src/build/mod.rs | 51 ++------------- core/tauri-utils/Cargo.toml | 3 +- .../acl.rs => tauri-utils/src/acl/build.rs} | 30 ++++++--- core/tauri-utils/src/acl/mod.rs | 62 ++++++++++++++++++- 7 files changed, 92 insertions(+), 60 deletions(-) rename core/{tauri-plugin/src/build/acl.rs => tauri-utils/src/acl/build.rs} (81%) diff --git a/core/tauri-build/Cargo.toml b/core/tauri-build/Cargo.toml index 5877ebb962bd..afa9fcb1fed4 100644 --- a/core/tauri-build/Cargo.toml +++ b/core/tauri-build/Cargo.toml @@ -30,7 +30,6 @@ anyhow = "1" quote = { version = "1", optional = true } tauri-codegen = { version = "2.0.0-alpha.12", path = "../tauri-codegen", optional = true } tauri-utils = { version = "2.0.0-alpha.12", path = "../tauri-utils", features = [ "build", "resources" ] } -tauri-plugin = { version = "0.1.0", path = "../tauri-plugin", features = [ "build" ] } cargo_toml = "0.17" serde = "1" serde_json = "1" diff --git a/core/tauri-build/src/acl.rs b/core/tauri-build/src/acl.rs index ad30681620f8..5127f67f226b 100644 --- a/core/tauri-build/src/acl.rs +++ b/core/tauri-build/src/acl.rs @@ -152,7 +152,7 @@ pub fn parse_capabilities(capabilities_path_pattern: &str) -> Result Result> { let permission_map = - tauri_plugin::acl::read_permissions().context("failed to read plugin permissions")?; + tauri_utils::acl::build::read_permissions().context("failed to read plugin permissions")?; let mut processed = HashMap::new(); for (plugin_name, permission_files) in permission_map { diff --git a/core/tauri-plugin/Cargo.toml b/core/tauri-plugin/Cargo.toml index 47cb68dea874..21e992018161 100644 --- a/core/tauri-plugin/Cargo.toml +++ b/core/tauri-plugin/Cargo.toml @@ -13,7 +13,6 @@ rust-version = { workspace = true } build = [ "dep:serde", "dep:cargo_metadata", - "dep:thiserror", "dep:serde_json", "dep:glob", "dep:toml", @@ -22,11 +21,11 @@ build = [ [dependencies] serde = { version = "1", optional = true } -thiserror = { version = "1", optional = true } cargo_metadata = { version = "0.18", optional = true } tauri-utils = { version = "2.0.0-alpha.12", default-features = false, path = "../tauri-utils", features = [ "schema", ] } +tauri = { version = "2.0.0-alpha.20", default-features = false, path = "../tauri" } serde_json = { version = "1", optional = true } glob = { version = "0.3", optional = true } toml = { version = "0.8", optional = true } diff --git a/core/tauri-plugin/src/build/mod.rs b/core/tauri-plugin/src/build/mod.rs index f54374972273..72895919b3ce 100644 --- a/core/tauri-plugin/src/build/mod.rs +++ b/core/tauri-plugin/src/build/mod.rs @@ -9,50 +9,7 @@ use std::{ }; use cargo_metadata::{Metadata, MetadataCommand}; -use thiserror::Error; - -pub mod acl; - -#[derive(Debug, Error)] -pub enum Error { - #[error("expected build script env var {0}, but it was not found - ensure this is called in a build script")] - BuildVar(String), - - #[error("plugin names cannot contain underscores")] - CrateName, - - #[error("package.links field in the Cargo manifest is not set, it should be set to the same as package.name")] - LinksMissing, - - #[error( - "package.links field in the Cargo manifest MUST be set to the same value as package.name" - )] - LinksName, - - #[error("failed to read file: {0}")] - ReadFile(std::io::Error), - - #[error("failed to write file: {0}")] - WriteFile(std::io::Error), - - #[error("failed to create file: {0}")] - CreateFile(std::io::Error), - - #[error("failed to execute: {0}")] - Metadata(#[from] cargo_metadata::Error), - - #[error("failed to run glob: {0}")] - Glob(#[from] glob::PatternError), - - #[error("failed to parse TOML: {0}")] - Toml(#[from] toml::de::Error), - - #[error("failed to parse JSON: {0}")] - Json(#[from] serde_json::Error), - - #[error("unknown permission format {0}")] - UnknownPermissionFormat(String), -} +use tauri_utils::acl::{self, Error}; pub struct Builder<'a> { commands: &'a [&'static str], @@ -94,8 +51,8 @@ impl<'a> Builder<'a> { autogenerate_command_permissions(commands_dir, self.commands); } - acl::define_permissions("./permissions/**/*.*")?; - acl::generate_schema()?; + acl::build::define_permissions("./permissions/**/*.*")?; + acl::build::generate_schema()?; let metadata = find_metadata()?; println!("{metadata:#?}"); @@ -114,7 +71,7 @@ fn autogenerate_command_permissions(path: &Path, commands: &[&str]) { let schema_path = (1..components_len) .map(|_| "..") .collect::() - .join(acl::PERMISSION_SCHEMA_FILE_NAME); + .join(acl::build::PERMISSION_SCHEMA_FILE_NAME); for command in commands { let slugified_command = command.replace('_', "-"); diff --git a/core/tauri-utils/Cargo.toml b/core/tauri-utils/Cargo.toml index 5e27063c068d..23c8bff7660a 100644 --- a/core/tauri-utils/Cargo.toml +++ b/core/tauri-utils/Cargo.toml @@ -39,12 +39,13 @@ semver = "1" infer = "0.15" dunce = "1" log = "0.4.20" +cargo_metadata = { version = "0.18", optional = true } [target."cfg(target_os = \"linux\")".dependencies] heck = "0.4" [features] -build = [ "proc-macro2", "quote" ] +build = [ "proc-macro2", "quote", "cargo_metadata"] compression = [ "brotli" ] schema = [ "schemars" ] isolation = [ "aes-gcm", "getrandom", "serialize-to-javascript" ] diff --git a/core/tauri-plugin/src/build/acl.rs b/core/tauri-utils/src/acl/build.rs similarity index 81% rename from core/tauri-plugin/src/build/acl.rs rename to core/tauri-utils/src/acl/build.rs index f1ba543e898c..b5f951ee9468 100644 --- a/core/tauri-plugin/src/build/acl.rs +++ b/core/tauri-utils/src/acl/build.rs @@ -2,6 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT +//! ACL items that are only useful inside of build script/codegen context. + use std::{ collections::HashMap, env::vars_os, @@ -11,14 +13,20 @@ use std::{ path::PathBuf, }; -use super::Error; +use crate::acl::Error; +use crate::acl::{Commands, Permission, Scopes}; use serde::Deserialize; -use tauri_utils::acl::{Commands, Permission, Scopes}; -const PERMISSION_FILES_PATH_KEY: &str = "PERMISSION_FILES_PATH"; -const PERMISSION_FILE_EXTENSIONS: &[&str] = &["json", "toml"]; -pub(crate) const PERMISSION_SCHEMA_FILE_NAME: &str = ".schema.json"; +/// Cargo cfg key for permissions file paths +pub const PERMISSION_FILES_PATH_KEY: &str = "PERMISSION_FILES_PATH"; + +/// Allowed permission file extensions +pub const PERMISSION_FILE_EXTENSIONS: &[&str] = &["json", "toml"]; + +/// Known filename of a permission schema +pub const PERMISSION_SCHEMA_FILE_NAME: &str = ".schema.json"; +/// A set of permissions or other permission sets. #[derive(Debug, Deserialize, schemars::JsonSchema)] pub struct PermissionSet { /// A unique identifier for the permission. @@ -54,14 +62,20 @@ pub struct DefaultPermission { /// Permission file that can define a default permission, a set of permissions or a list of inlined permissions. #[derive(Debug, Deserialize, schemars::JsonSchema)] pub struct PermissionFile { + /// The default permission set for the plugin pub default: Option, + + /// A list of permissions sets defined #[serde(default)] pub set: Vec, + + /// A list of inlined permissions #[serde(default)] pub permission: Vec, } -pub(crate) fn define_permissions(pattern: &str) -> Result<(), Error> { +/// Write the permissions to a temporary directory and pass it to the immediate consuming crate. +pub fn define_permissions(pattern: &str) -> Result<(), Error> { let permission_files = glob::glob(pattern)? .flatten() .flat_map(|p| p.canonicalize()) @@ -101,7 +115,8 @@ pub(crate) fn define_permissions(pattern: &str) -> Result<(), Error> { Ok(()) } -pub(crate) fn generate_schema() -> Result<(), Error> { +/// Generate and write a schema based on the format of a [`PermissionFile`]. +pub fn generate_schema() -> Result<(), Error> { let schema = schemars::schema_for!(PermissionFile); let schema_str = serde_json::to_string_pretty(&schema).unwrap(); let out_path = PathBuf::from("permissions").join(PERMISSION_SCHEMA_FILE_NAME); @@ -111,6 +126,7 @@ pub(crate) fn generate_schema() -> Result<(), Error> { Ok(()) } +/// Read all permissions listed from the defined cargo cfg key value. pub fn read_permissions() -> Result>, Error> { let mut permissions_map = HashMap::new(); diff --git a/core/tauri-utils/src/acl/mod.rs b/core/tauri-utils/src/acl/mod.rs index 0588050878e2..bff355afc070 100644 --- a/core/tauri-utils/src/acl/mod.rs +++ b/core/tauri-utils/src/acl/mod.rs @@ -6,15 +6,75 @@ use serde::{Deserialize, Serialize}; use std::num::NonZeroU64; +use thiserror::Error; pub use self::{identifier::*, value::*}; +#[cfg(feature = "build")] +pub mod build; pub mod capability; pub mod identifier; pub mod plugin; pub mod resolved; pub mod value; +/// Possible errors while processing ACL files. +#[derive(Debug, Error)] +pub enum Error { + /// Could not find an environmental variable that is set inside of build scripts. + /// + /// Whatever generated this should be called inside of a build script. + #[error("expected build script env var {0}, but it was not found - ensure this is called in a build script")] + BuildVar(String), + + /// Plugin name doesn't follow Tauri standards + #[error("plugin names cannot contain underscores")] + CrateName, + + /// The links field in the manifest **MUST** be set and match the name of the crate. + #[error("package.links field in the Cargo manifest is not set, it should be set to the same as package.name")] + LinksMissing, + + /// The links field in the manifest **MUST** match the name of the crate. + #[error( + "package.links field in the Cargo manifest MUST be set to the same value as package.name" + )] + LinksName, + + /// IO error while reading a file + #[error("failed to read file: {0}")] + ReadFile(std::io::Error), + + /// IO error while writing a file + #[error("failed to write file: {0}")] + WriteFile(std::io::Error), + + /// IO error while creating a file + #[error("failed to create file: {0}")] + CreateFile(std::io::Error), + + /// [`cargo_metadata`] was not able to complete successfully + #[cfg(feature = "build")] + #[error("failed to execute: {0}")] + Metadata(#[from] ::cargo_metadata::Error), + + /// Invalid glob + #[error("failed to run glob: {0}")] + Glob(#[from] glob::PatternError), + + /// Invalid TOML encountered + #[error("failed to parse TOML: {0}")] + Toml(#[from] toml::de::Error), + + /// Invalid JSON encountered + #[error("failed to parse JSON: {0}")] + Json(#[from] serde_json::Error), + + /// Invalid permissions file format + #[error("unknown permission format {0}")] + UnknownPermissionFormat(String), +} + /// Allowed and denied commands inside a permission. /// /// If two commands clash inside of `allow` and `deny`, it should be denied by default. @@ -97,7 +157,7 @@ pub enum ExecutionContext { } #[cfg(feature = "build")] -mod build { +mod build_ { use crate::tokens::*; use super::*; From f460f2702ea2a438fc6cf7cbcd51e17ab9e9817c Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Mon, 15 Jan 2024 16:58:23 -0300 Subject: [PATCH 30/69] enable schema and glob [skip ci] --- core/tauri-config-schema/Cargo.toml | 2 +- core/tauri-plugin/Cargo.toml | 2 +- core/tauri-utils/Cargo.toml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/tauri-config-schema/Cargo.toml b/core/tauri-config-schema/Cargo.toml index 11654dd2fa5c..7bf09a8e227d 100644 --- a/core/tauri-config-schema/Cargo.toml +++ b/core/tauri-config-schema/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" publish = false [build-dependencies] -tauri-utils = { features = ["schema"], path = "../tauri-utils" } +tauri-utils = { path = "../tauri-utils" } schemars = { version = "0.8", features = ["url", "preserve_order"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/core/tauri-plugin/Cargo.toml b/core/tauri-plugin/Cargo.toml index 21e992018161..1823939132fe 100644 --- a/core/tauri-plugin/Cargo.toml +++ b/core/tauri-plugin/Cargo.toml @@ -23,7 +23,7 @@ build = [ serde = { version = "1", optional = true } cargo_metadata = { version = "0.18", optional = true } tauri-utils = { version = "2.0.0-alpha.12", default-features = false, path = "../tauri-utils", features = [ - "schema", + #"schema", ] } tauri = { version = "2.0.0-alpha.20", default-features = false, path = "../tauri" } serde_json = { version = "1", optional = true } diff --git a/core/tauri-utils/Cargo.toml b/core/tauri-utils/Cargo.toml index 23c8bff7660a..13bc93ece102 100644 --- a/core/tauri-utils/Cargo.toml +++ b/core/tauri-utils/Cargo.toml @@ -45,11 +45,11 @@ cargo_metadata = { version = "0.18", optional = true } heck = "0.4" [features] -build = [ "proc-macro2", "quote", "cargo_metadata"] +build = [ "proc-macro2", "quote", "cargo_metadata", "glob", "schema" ] compression = [ "brotli" ] schema = [ "schemars" ] isolation = [ "aes-gcm", "getrandom", "serialize-to-javascript" ] process-relaunch-dangerous-allow-symlink-macos = [ ] config-json5 = [ "json5" ] config-toml = [] -resources = [ "glob", "walkdir" ] +resources = [ "walkdir" ] From f4df3ade4c532b8de382bf097933ad068fe1f004 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Mon, 15 Jan 2024 17:06:40 -0300 Subject: [PATCH 31/69] fix glob [skip ci] --- core/tauri-utils/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/tauri-utils/Cargo.toml b/core/tauri-utils/Cargo.toml index 13bc93ece102..f3331456f6f1 100644 --- a/core/tauri-utils/Cargo.toml +++ b/core/tauri-utils/Cargo.toml @@ -52,4 +52,4 @@ isolation = [ "aes-gcm", "getrandom", "serialize-to-javascript" ] process-relaunch-dangerous-allow-symlink-macos = [ ] config-json5 = [ "json5" ] config-toml = [] -resources = [ "walkdir" ] +resources = [ "glob", "walkdir" ] From 59f800dad8a0bde7af6972e1fd74eda615de81a1 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Mon, 15 Jan 2024 17:09:33 -0300 Subject: [PATCH 32/69] fix capability schema [skip ci] --- core/tauri-build/src/acl.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/tauri-build/src/acl.rs b/core/tauri-build/src/acl.rs index 5127f67f226b..a4646db3646e 100644 --- a/core/tauri-build/src/acl.rs +++ b/core/tauri-build/src/acl.rs @@ -11,8 +11,8 @@ use std::{ use anyhow::{Context, Result}; use schemars::{ - gen::SchemaGenerator, schema::{InstanceType, Metadata, RootSchema, Schema, SchemaObject, SubschemaValidation}, + schema_for, }; use serde::Deserialize; use tauri_utils::acl::{capability::Capability, plugin::Manifest, Permission, PermissionSet}; @@ -20,7 +20,7 @@ use tauri_utils::acl::{capability::Capability, plugin::Manifest, Permission, Per const CAPABILITY_FILE_EXTENSIONS: &[&str] = &["json", "toml"]; const CAPABILITIES_SCHEMA_FILE_NAME: &str = ".schema.json"; -#[derive(Deserialize)] +#[derive(Deserialize, schemars::JsonSchema)] #[serde(untagged)] enum CapabilityFile { Capability(Capability), @@ -28,7 +28,7 @@ enum CapabilityFile { } fn capabilities_schema(plugin_manifests: &HashMap) -> RootSchema { - let mut schema = SchemaGenerator::default().into_root_schema_for::(); + let mut schema = schema_for!(CapabilityFile); let mut permission_schemas = Vec::new(); for (plugin, manifest) in plugin_manifests { From c1674388ddd9ab799ea6c9d265bc8a08aaa58269 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Mon, 15 Jan 2024 17:54:03 -0300 Subject: [PATCH 33/69] enhance schema for permission set possible values [skip ci] --- core/tauri-build/src/acl.rs | 63 ++++++++++------------- core/tauri-plugin/src/build/mod.rs | 4 +- core/tauri-utils/src/acl/build.rs | 82 ++++++++++++++++++++++++++++-- examples/api/src-tauri/Cargo.lock | 4 +- 4 files changed, 108 insertions(+), 45 deletions(-) diff --git a/core/tauri-build/src/acl.rs b/core/tauri-build/src/acl.rs index a4646db3646e..e47b7e556259 100644 --- a/core/tauri-build/src/acl.rs +++ b/core/tauri-build/src/acl.rs @@ -30,52 +30,41 @@ enum CapabilityFile { fn capabilities_schema(plugin_manifests: &HashMap) -> RootSchema { let mut schema = schema_for!(CapabilityFile); + fn schema_from(plugin: &str, id: &str, description: Option<&str>) -> Schema { + Schema::Object(SchemaObject { + metadata: Some(Box::new(Metadata { + description: description + .as_ref() + .map(|d| format!("{plugin}:{id} -> {d}")), + ..Default::default() + })), + instance_type: Some(InstanceType::String.into()), + enum_values: Some(vec![serde_json::Value::String(format!("{plugin}:{id}"))]), + ..Default::default() + }) + } + let mut permission_schemas = Vec::new(); + for (plugin, manifest) in plugin_manifests { for (set_id, set) in &manifest.permission_sets { - permission_schemas.push(Schema::Object(SchemaObject { - metadata: Some(Box::new(Metadata { - description: Some(format!("{plugin}:{set_id} -> {}", set.description)), - ..Default::default() - })), - instance_type: Some(InstanceType::String.into()), - enum_values: Some(vec![serde_json::Value::String(format!( - "{plugin}:{set_id}" - ))]), - ..Default::default() - })); + permission_schemas.push(schema_from(plugin, set_id, Some(&set.description))); } if let Some(default) = &manifest.default_permission { - permission_schemas.push(Schema::Object(SchemaObject { - metadata: Some(Box::new(Metadata { - description: default - .description - .as_ref() - .map(|d| format!("{plugin}:default -> {d}")), - ..Default::default() - })), - instance_type: Some(InstanceType::String.into()), - enum_values: Some(vec![serde_json::Value::String(format!("{plugin}:default"))]), - ..Default::default() - })); + permission_schemas.push(schema_from( + plugin, + "default", + default.description.as_deref(), + )); } for (permission_id, permission) in &manifest.permissions { - permission_schemas.push(Schema::Object(SchemaObject { - metadata: Some(Box::new(Metadata { - description: permission - .description - .as_ref() - .map(|d| format!("{plugin}:{permission_id} -> {d}")), - ..Default::default() - })), - instance_type: Some(InstanceType::String.into()), - enum_values: Some(vec![serde_json::Value::String(format!( - "{plugin}:{permission_id}" - ))]), - ..Default::default() - })); + permission_schemas.push(schema_from( + plugin, + permission_id, + permission.description.as_deref(), + )); } } diff --git a/core/tauri-plugin/src/build/mod.rs b/core/tauri-plugin/src/build/mod.rs index 72895919b3ce..ec5073962225 100644 --- a/core/tauri-plugin/src/build/mod.rs +++ b/core/tauri-plugin/src/build/mod.rs @@ -51,8 +51,8 @@ impl<'a> Builder<'a> { autogenerate_command_permissions(commands_dir, self.commands); } - acl::build::define_permissions("./permissions/**/*.*")?; - acl::build::generate_schema()?; + let permissions = acl::build::define_permissions("./permissions/**/*.*")?; + acl::build::generate_schema(&permissions)?; let metadata = find_metadata()?; println!("{metadata:#?}"); diff --git a/core/tauri-utils/src/acl/build.rs b/core/tauri-utils/src/acl/build.rs index b5f951ee9468..bf786df38a8e 100644 --- a/core/tauri-utils/src/acl/build.rs +++ b/core/tauri-utils/src/acl/build.rs @@ -15,6 +15,10 @@ use std::{ use crate::acl::Error; use crate::acl::{Commands, Permission, Scopes}; +use schemars::{ + schema::{InstanceType, Metadata, RootSchema, Schema, SchemaObject, SubschemaValidation}, + schema_for, +}; use serde::Deserialize; /// Cargo cfg key for permissions file paths @@ -69,13 +73,16 @@ pub struct PermissionFile { #[serde(default)] pub set: Vec, + /// Test something!! + pub test: Option, + /// A list of inlined permissions #[serde(default)] pub permission: Vec, } /// Write the permissions to a temporary directory and pass it to the immediate consuming crate. -pub fn define_permissions(pattern: &str) -> Result<(), Error> { +pub fn define_permissions(pattern: &str) -> Result, Error> { let permission_files = glob::glob(pattern)? .flatten() .flat_map(|p| p.canonicalize()) @@ -112,12 +119,79 @@ pub fn define_permissions(pattern: &str) -> Result<(), Error> { permission_files_path.display() ); - Ok(()) + parse_permissions(permission_files) +} + +fn permissions_schema(permissions: &[PermissionFile]) -> RootSchema { + let mut schema = schema_for!(PermissionFile); + + fn schema_from(id: &str, description: Option<&str>) -> Schema { + Schema::Object(SchemaObject { + metadata: Some(Box::new(Metadata { + description: description.map(|d| format!("{id} -> {d}")), + ..Default::default() + })), + instance_type: Some(InstanceType::String.into()), + enum_values: Some(vec![serde_json::Value::String(id.into())]), + ..Default::default() + }) + } + + let mut permission_schemas = Vec::new(); + for file in permissions { + if let Some(permission) = &file.default { + permission_schemas.push(schema_from("default", permission.description.as_deref())); + } + + permission_schemas.extend( + file + .set + .iter() + .map(|set| schema_from(&set.identifier, Some(set.description.as_str()))) + .collect::>(), + ); + + permission_schemas.extend( + file + .permission + .iter() + .map(|permission| schema_from(&permission.identifier, permission.description.as_deref())) + .collect::>(), + ); + } + + if let Some(Schema::Object(obj)) = schema.definitions.get_mut("PermissionSet") { + if let Some(Schema::Object(permissions_prop_schema)) = + obj.object().properties.get_mut("permissions") + { + permissions_prop_schema.array().items.replace( + Schema::Object(SchemaObject { + reference: Some("#/definitions/PermissionKind".into()), + ..Default::default() + }) + .into(), + ); + + schema.definitions.insert( + "PermissionKind".into(), + Schema::Object(SchemaObject { + instance_type: Some(InstanceType::String.into()), + subschemas: Some(Box::new(SubschemaValidation { + one_of: Some(permission_schemas), + ..Default::default() + })), + ..Default::default() + }), + ); + } + } + + schema } /// Generate and write a schema based on the format of a [`PermissionFile`]. -pub fn generate_schema() -> Result<(), Error> { - let schema = schemars::schema_for!(PermissionFile); +pub fn generate_schema(permissions: &[PermissionFile]) -> Result<(), Error> { + let schema = permissions_schema(permissions); let schema_str = serde_json::to_string_pretty(&schema).unwrap(); let out_path = PathBuf::from("permissions").join(PERMISSION_SCHEMA_FILE_NAME); diff --git a/examples/api/src-tauri/Cargo.lock b/examples/api/src-tauri/Cargo.lock index e24bd903dbfc..e469964a63bb 100644 --- a/examples/api/src-tauri/Cargo.lock +++ b/examples/api/src-tauri/Cargo.lock @@ -3560,7 +3560,6 @@ dependencies = [ "serde_json", "swift-rs", "tauri-codegen", - "tauri-plugin", "tauri-utils", "tauri-winres", "toml 0.8.2", @@ -3612,8 +3611,8 @@ dependencies = [ "schemars", "serde", "serde_json", + "tauri", "tauri-utils", - "thiserror", "toml 0.8.2", ] @@ -3683,6 +3682,7 @@ version = "2.0.0-alpha.12" dependencies = [ "aes-gcm", "brotli", + "cargo_metadata", "ctor", "dunce", "getrandom 0.2.10", From 0e1267704fd89ef4c1bfc53c03fbd61397bc0c6c Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Tue, 16 Jan 2024 10:14:07 -0300 Subject: [PATCH 34/69] permission set can reference other sets [skip ci] --- core/tauri-codegen/src/context/resolve_acl.rs | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/core/tauri-codegen/src/context/resolve_acl.rs b/core/tauri-codegen/src/context/resolve_acl.rs index 7899029d3ce5..3ac97dc79672 100644 --- a/core/tauri-codegen/src/context/resolve_acl.rs +++ b/core/tauri-codegen/src/context/resolve_acl.rs @@ -11,7 +11,7 @@ use tauri_utils::acl::{ capability::{Capability, CapabilityContext}, plugin::Manifest, resolved::{CommandKey, Resolved, ResolvedCommand, ResolvedScope}, - ExecutionContext, Permission, + ExecutionContext, Permission, PermissionSet, }; #[derive(Debug, Default)] @@ -173,6 +173,29 @@ fn resolve_command( } } +// get the permissions from a permission set +fn get_permission_set_permissions<'a>( + manifest: &'a Manifest, + set: &'a PermissionSet, +) -> Result, String> { + let mut permissions = Vec::new(); + + for p in &set.permissions { + if let Some(permission) = manifest.permissions.get(p) { + permissions.push(permission); + } else if let Some(permission_set) = manifest.permission_sets.get(p) { + permissions.extend(get_permission_set_permissions(manifest, permission_set)?); + } else { + return Err(format!( + "permission {p} not found from set {}", + set.identifier + )); + } + } + + Ok(permissions) +} + fn get_permissions<'a>( plugin_name: &'a str, permission_name: &'a str, @@ -190,16 +213,7 @@ fn get_permissions<'a>( || format!("plugin {plugin_name} has no default permission"), )?]) } else if let Some(set) = manifest.permission_sets.get(permission_name) { - let mut resolved = Vec::new(); - for p in &set.permissions { - resolved.push( - manifest - .permissions - .get(p) - .ok_or_else(|| format!("permission {p} in set {permission_name} not found"))?, - ); - } - Ok(resolved) + get_permission_set_permissions(manifest, set) } else if let Some(permission) = manifest.permissions.get(permission_name) { Ok(vec![permission]) } else { From a64c7b6129f47e262576302e407b4e1b90b33e12 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Tue, 16 Jan 2024 13:56:03 -0300 Subject: [PATCH 35/69] setup tests for resolving ACL --- Cargo.toml | 2 +- core/tauri-build/src/acl.rs | 115 +-------- core/tauri-build/src/lib.rs | 5 +- core/tauri-codegen/src/context.rs | 11 +- core/tauri-codegen/src/context/resolve_acl.rs | 224 ----------------- core/tauri-utils/src/acl/build.rs | 69 +++++- core/tauri-utils/src/acl/mod.rs | 39 +++ core/tauri-utils/src/acl/plugin.rs | 52 +++- core/tauri-utils/src/acl/resolved.rs | 225 +++++++++++++++++- core/tests/acl/Cargo.toml | 16 ++ .../fixtures/capabilities/basic-ping/cap.toml | 4 + .../basic-ping/required-plugins.json | 1 + .../tests/acl/fixtures/plugins/ping/ping.toml | 9 + .../acl_tests__tests__basic-ping.snap | 29 +++ core/tests/acl/src/lib.rs | 60 +++++ 15 files changed, 519 insertions(+), 342 deletions(-) delete mode 100644 core/tauri-codegen/src/context/resolve_acl.rs create mode 100644 core/tests/acl/Cargo.toml create mode 100644 core/tests/acl/fixtures/capabilities/basic-ping/cap.toml create mode 100644 core/tests/acl/fixtures/capabilities/basic-ping/required-plugins.json create mode 100644 core/tests/acl/fixtures/plugins/ping/ping.toml create mode 100644 core/tests/acl/fixtures/snapshots/acl_tests__tests__basic-ping.snap create mode 100644 core/tests/acl/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 00bce404c9b5..1d1eceff0399 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ members = [ # examples that should be tested by default "examples/plugins/*" -] +, "core/tests/acl"] exclude = [ # examples that can be compiled with the tauri CLI diff --git a/core/tauri-build/src/acl.rs b/core/tauri-build/src/acl.rs index e47b7e556259..1285d405c0f4 100644 --- a/core/tauri-build/src/acl.rs +++ b/core/tauri-build/src/acl.rs @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MIT use std::{ - collections::HashMap, + collections::BTreeMap, fs::File, io::{BufWriter, Write}, path::PathBuf, @@ -14,20 +14,11 @@ use schemars::{ schema::{InstanceType, Metadata, RootSchema, Schema, SchemaObject, SubschemaValidation}, schema_for, }; -use serde::Deserialize; -use tauri_utils::acl::{capability::Capability, plugin::Manifest, Permission, PermissionSet}; +use tauri_utils::acl::{build::CapabilityFile, capability::Capability, plugin::Manifest}; -const CAPABILITY_FILE_EXTENSIONS: &[&str] = &["json", "toml"]; const CAPABILITIES_SCHEMA_FILE_NAME: &str = ".schema.json"; -#[derive(Deserialize, schemars::JsonSchema)] -#[serde(untagged)] -enum CapabilityFile { - Capability(Capability), - List { capabilities: Vec }, -} - -fn capabilities_schema(plugin_manifests: &HashMap) -> RootSchema { +fn capabilities_schema(plugin_manifests: &BTreeMap) -> RootSchema { let mut schema = schema_for!(CapabilityFile); fn schema_from(plugin: &str, id: &str, description: Option<&str>) -> Schema { @@ -86,7 +77,7 @@ fn capabilities_schema(plugin_manifests: &HashMap) -> RootSche schema } -pub(crate) fn generate_schema(plugin_manifests: &HashMap) -> Result<()> { +pub fn generate_schema(plugin_manifests: &BTreeMap) -> Result<()> { let schema = capabilities_schema(plugin_manifests); let schema_str = serde_json::to_string_pretty(&schema).unwrap(); let out_path = PathBuf::from("capabilities").join(CAPABILITIES_SCHEMA_FILE_NAME); @@ -96,107 +87,21 @@ pub(crate) fn generate_schema(plugin_manifests: &HashMap) -> R Ok(()) } -pub fn parse_capabilities(capabilities_path_pattern: &str) -> Result> { - let mut capabilities_map = HashMap::new(); - - for path in glob::glob(capabilities_path_pattern)? - .flatten() // filter extension - .filter(|p| { - p.extension() - .and_then(|e| e.to_str()) - .map(|e| CAPABILITY_FILE_EXTENSIONS.contains(&e)) - .unwrap_or_default() - }) - // filter schema file - .filter(|p| { - p.file_name() - .map(|name| name != CAPABILITIES_SCHEMA_FILE_NAME) - .unwrap_or(true) - }) - { - println!("cargo:rerun-if-changed={}", path.display()); - - let capability_file = std::fs::read_to_string(&path)?; - let ext = path.extension().unwrap().to_string_lossy().to_string(); - let capability: CapabilityFile = match ext.as_str() { - "toml" => toml::from_str(&capability_file)?, - "json" => serde_json::from_str(&capability_file)?, - _ => return Err(anyhow::anyhow!("unknown capability format")), - }; - - match capability { - CapabilityFile::Capability(capability) => { - capabilities_map.insert(capability.identifier.clone(), capability); - } - CapabilityFile::List { capabilities } => { - for capability in capabilities { - capabilities_map.insert(capability.identifier.clone(), capability); - } - } - } - } - - Ok(capabilities_map) -} - -pub(crate) fn get_plugin_manifests() -> Result> { +pub fn get_plugin_manifests() -> Result> { let permission_map = tauri_utils::acl::build::read_permissions().context("failed to read plugin permissions")?; - let mut processed = HashMap::new(); + let mut processed = BTreeMap::new(); for (plugin_name, permission_files) in permission_map { - let mut manifest = Manifest { - default_permission: None, - permissions: HashMap::new(), - permission_sets: HashMap::new(), - }; - - for permission_file in permission_files { - if let Some(default) = permission_file.default { - manifest.default_permission.replace(Permission { - identifier: "default".into(), - version: default.version, - description: default.description, - commands: default.commands, - scope: default.scope, - }); - } - - manifest.permissions.extend( - permission_file - .permission - .into_iter() - .map(|p| (p.identifier.clone(), p)) - .collect::>(), - ); - - manifest.permission_sets.extend( - permission_file - .set - .into_iter() - .map(|set| { - ( - set.identifier.clone(), - PermissionSet { - identifier: set.identifier, - description: set.description, - permissions: set.permissions, - }, - ) - }) - .collect::>(), - ); - } - - processed.insert(plugin_name, manifest); + processed.insert(plugin_name, Manifest::from_files(permission_files)); } Ok(processed) } -pub(crate) fn validate_capabilities( - plugin_manifests: &HashMap, - capabilities: &HashMap, +pub fn validate_capabilities( + plugin_manifests: &BTreeMap, + capabilities: &BTreeMap, ) -> Result<()> { for capability in capabilities.values() { for permission in &capability.permissions { diff --git a/core/tauri-build/src/lib.rs b/core/tauri-build/src/lib.rs index 4f6170e49748..6836ea32819b 100644 --- a/core/tauri-build/src/lib.rs +++ b/core/tauri-build/src/lib.rs @@ -18,6 +18,7 @@ use cargo_toml::Manifest; use heck::AsShoutySnakeCase; use tauri_utils::{ + acl::build::parse_capabilities, config::{BundleResources, Config, WebviewInstallMode}, resources::{external_binaries, ResourcePaths}, }; @@ -462,9 +463,9 @@ pub fn try_build(attributes: Attributes) -> Result<()> { serde_json::to_string(&plugin_manifests)?, )?; let capabilities = if let Some(pattern) = attributes.capabilities_path_pattern { - acl::parse_capabilities(pattern)? + parse_capabilities(pattern)? } else { - acl::parse_capabilities("./capabilities/**/*")? + parse_capabilities("./capabilities/**/*")? }; acl::generate_schema(&plugin_manifests)?; diff --git a/core/tauri-codegen/src/context.rs b/core/tauri-codegen/src/context.rs index 642158f8d234..e4c7c7483458 100644 --- a/core/tauri-codegen/src/context.rs +++ b/core/tauri-codegen/src/context.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -use std::collections::HashMap; +use std::collections::BTreeMap; use std::path::{Path, PathBuf}; use std::{ffi::OsStr, str::FromStr}; @@ -13,6 +13,7 @@ use sha2::{Digest, Sha256}; 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::{AppUrl, Config, PatternKind, WindowUrl}; use tauri_utils::html::{ @@ -22,8 +23,6 @@ use tauri_utils::platform::Target; use crate::embedded_assets::{AssetOptions, CspHashes, EmbeddedAssets, EmbeddedAssetsError}; -mod resolve_acl; - const PLUGIN_MANIFESTS_FILE_NAME: &str = "plugin-manifests.json"; const CAPABILITIES_FILE_NAME: &str = "capabilities.json"; @@ -382,7 +381,7 @@ pub fn context_codegen(data: ContextData) -> Result = if acl_file_path.exists() { + let acl: BTreeMap = if acl_file_path.exists() { let acl_file = std::fs::read_to_string(acl_file_path).expect("failed to read plugin manifest map"); serde_json::from_str(&acl_file).expect("failed to parse plugin manifest map") @@ -391,7 +390,7 @@ pub fn context_codegen(data: ContextData) -> Result = if capabilities_file_path.exists() { + let capabilities: BTreeMap = 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") @@ -399,7 +398,7 @@ pub fn context_codegen(data: ContextData) -> Result, - pub scope: Vec, - pub resolved_scope_key: usize, -} - -pub fn resolve( - acl: HashMap, - capabilities: HashMap, -) -> Result> { - let mut allowed_commands = HashMap::new(); - let mut denied_commands = HashMap::new(); - - let mut current_scope_id = 0; - let mut command_scopes = HashMap::new(); - let mut global_scope = Vec::new(); - - // resolve commands - for capability in capabilities.values() { - for permission_id in &capability.permissions { - let permission_name = permission_id.get_base(); - - if let Some(plugin_name) = permission_id.get_prefix() { - let permissions = get_permissions(plugin_name, permission_name, &acl)?; - - for permission in permissions { - if permission.commands.allow.is_empty() && permission.commands.deny.is_empty() { - // global scope - global_scope.push(permission.scope.clone()); - } else { - current_scope_id += 1; - command_scopes.insert(current_scope_id, permission.scope.clone()); - - for allowed_command in &permission.commands.allow { - resolve_command( - &mut allowed_commands, - format!("plugin:{plugin_name}|{allowed_command}"), - capability, - current_scope_id, - ); - } - - for denied_command in &permission.commands.deny { - resolve_command( - &mut denied_commands, - format!("plugin:{plugin_name}|{denied_command}"), - capability, - current_scope_id, - ); - } - } - } - } - } - } - - // resolve scopes - let mut resolved_scopes = BTreeMap::new(); - - for allowed in allowed_commands.values_mut() { - allowed.scope.sort(); - - let mut hasher = DefaultHasher::new(); - allowed.scope.hash(&mut hasher); - let hash = hasher.finish() as usize; - - allowed.resolved_scope_key = hash; - - let resolved_scope = ResolvedScope { - allow: allowed - .scope - .iter() - .flat_map(|s| command_scopes.get(s).unwrap().allow.clone()) - .collect(), - deny: allowed - .scope - .iter() - .flat_map(|s| command_scopes.get(s).unwrap().deny.clone()) - .collect(), - }; - - resolved_scopes.insert(hash, resolved_scope); - } - - let global_scope = ResolvedScope { - allow: global_scope - .iter_mut() - .flat_map(|s| s.allow.take()) - .collect(), - deny: global_scope - .iter_mut() - .flat_map(|s| s.deny.take()) - .collect(), - }; - - let resolved = Resolved { - allowed_commands: allowed_commands - .into_iter() - .map(|(key, cmd)| { - ( - key, - ResolvedCommand { - windows: cmd.windows, - scope: cmd.resolved_scope_key, - }, - ) - }) - .collect(), - denied_commands: denied_commands - .into_iter() - .map(|(key, cmd)| { - ( - key, - ResolvedCommand { - windows: cmd.windows, - scope: cmd.resolved_scope_key, - }, - ) - }) - .collect(), - command_scope: resolved_scopes, - global_scope, - }; - - Ok(resolved) -} - -fn resolve_command( - commands: &mut HashMap, - command: String, - capability: &Capability, - scope_id: usize, -) { - let contexts = match &capability.context { - CapabilityContext::Local => { - vec![ExecutionContext::Local] - } - CapabilityContext::Remote { dangerous_remote } => dangerous_remote - .iter() - .map(|domain| ExecutionContext::Remote { - domain: domain.to_string(), - }) - .collect(), - }; - - for context in contexts { - let resolved = commands - .entry(CommandKey { - name: command.clone(), - context, - }) - .or_default(); - - resolved.windows.extend(capability.windows.clone()); - resolved.scope.push(scope_id); - } -} - -// get the permissions from a permission set -fn get_permission_set_permissions<'a>( - manifest: &'a Manifest, - set: &'a PermissionSet, -) -> Result, String> { - let mut permissions = Vec::new(); - - for p in &set.permissions { - if let Some(permission) = manifest.permissions.get(p) { - permissions.push(permission); - } else if let Some(permission_set) = manifest.permission_sets.get(p) { - permissions.extend(get_permission_set_permissions(manifest, permission_set)?); - } else { - return Err(format!( - "permission {p} not found from set {}", - set.identifier - )); - } - } - - Ok(permissions) -} - -fn get_permissions<'a>( - plugin_name: &'a str, - permission_name: &'a str, - acl: &'a HashMap, -) -> Result, String> { - let manifest = acl.get(plugin_name).ok_or_else(|| { - format!( - "unknown plugin {plugin_name}, expected one of {:?}", - acl.keys().cloned().collect::>().join(", ") - ) - })?; - - if permission_name == "default" { - Ok(vec![manifest.default_permission.as_ref().ok_or_else( - || format!("plugin {plugin_name} has no default permission"), - )?]) - } else if let Some(set) = manifest.permission_sets.get(permission_name) { - get_permission_set_permissions(manifest, set) - } else if let Some(permission) = manifest.permissions.get(permission_name) { - Ok(vec![permission]) - } else { - Err(format!( - "unknown permission {permission_name} for plugin {plugin_name}" - )) - } -} diff --git a/core/tauri-utils/src/acl/build.rs b/core/tauri-utils/src/acl/build.rs index bf786df38a8e..446cf1634a75 100644 --- a/core/tauri-utils/src/acl/build.rs +++ b/core/tauri-utils/src/acl/build.rs @@ -5,7 +5,7 @@ //! ACL items that are only useful inside of build script/codegen context. use std::{ - collections::HashMap, + collections::{BTreeMap, HashMap}, env::vars_os, fs::File, io::{BufWriter, Write}, @@ -21,6 +21,8 @@ use schemars::{ }; use serde::Deserialize; +use super::capability::Capability; + /// Cargo cfg key for permissions file paths pub const PERMISSION_FILES_PATH_KEY: &str = "PERMISSION_FILES_PATH"; @@ -30,6 +32,12 @@ pub const PERMISSION_FILE_EXTENSIONS: &[&str] = &["json", "toml"]; /// Known filename of a permission schema pub const PERMISSION_SCHEMA_FILE_NAME: &str = ".schema.json"; +/// Allowed capability file extensions +const CAPABILITY_FILE_EXTENSIONS: &[&str] = &["json", "toml"]; + +/// Known filename of a capability schema +const CAPABILITIES_SCHEMA_FILE_NAME: &str = ".schema.json"; + /// A set of permissions or other permission sets. #[derive(Debug, Deserialize, schemars::JsonSchema)] pub struct PermissionSet { @@ -81,6 +89,19 @@ pub struct PermissionFile { pub permission: Vec, } +/// Capability formats accepted in a capability file. +#[derive(Deserialize, schemars::JsonSchema)] +#[serde(untagged)] +pub enum CapabilityFile { + /// A single capability. + Capability(Capability), + /// A list of capabilities. + List { + /// The list of capabilities. + capabilities: Vec, + }, +} + /// Write the permissions to a temporary directory and pass it to the immediate consuming crate. pub fn define_permissions(pattern: &str) -> Result, Error> { let permission_files = glob::glob(pattern)? @@ -122,6 +143,52 @@ pub fn define_permissions(pattern: &str) -> Result, Error> { parse_permissions(permission_files) } +/// Parses all capability files with the given glob pattern. +pub fn parse_capabilities( + capabilities_path_pattern: &str, +) -> Result, Error> { + let mut capabilities_map = BTreeMap::new(); + + for path in glob::glob(capabilities_path_pattern)? + .flatten() // filter extension + .filter(|p| { + p.extension() + .and_then(|e| e.to_str()) + .map(|e| CAPABILITY_FILE_EXTENSIONS.contains(&e)) + .unwrap_or_default() + }) + // filter schema file + .filter(|p| { + p.file_name() + .map(|name| name != CAPABILITIES_SCHEMA_FILE_NAME) + .unwrap_or(true) + }) + { + println!("cargo:rerun-if-changed={}", path.display()); + + let capability_file = std::fs::read_to_string(&path).map_err(Error::ReadFile)?; + let ext = path.extension().unwrap().to_string_lossy().to_string(); + let capability: CapabilityFile = match ext.as_str() { + "toml" => toml::from_str(&capability_file)?, + "json" => serde_json::from_str(&capability_file)?, + _ => return Err(Error::UnknownCapabilityFormat(ext)), + }; + + match capability { + CapabilityFile::Capability(capability) => { + capabilities_map.insert(capability.identifier.clone(), capability); + } + CapabilityFile::List { capabilities } => { + for capability in capabilities { + capabilities_map.insert(capability.identifier.clone(), capability); + } + } + } + } + + Ok(capabilities_map) +} + fn permissions_schema(permissions: &[PermissionFile]) -> RootSchema { let mut schema = schema_for!(PermissionFile); diff --git a/core/tauri-utils/src/acl/mod.rs b/core/tauri-utils/src/acl/mod.rs index bff355afc070..569764336069 100644 --- a/core/tauri-utils/src/acl/mod.rs +++ b/core/tauri-utils/src/acl/mod.rs @@ -73,6 +73,45 @@ pub enum Error { /// Invalid permissions file format #[error("unknown permission format {0}")] UnknownPermissionFormat(String), + + /// Invalid capabilities file format + #[error("unknown capability format {0}")] + UnknownCapabilityFormat(String), + + /// Permission referenced in set not found. + #[error("permission {permission} not found from set {set}")] + SetPermissionNotFound { + /// Permission identifier. + permission: String, + /// Set identifier. + set: String, + }, + + /// Plugin has no default permission. + #[error("plugin {plugin} has no default permission")] + MissingDefaultPermission { + /// Plugin name. + plugin: String, + }, + + /// Unknown plugin. + #[error("unknown plugin {plugin}, expected one of {available}")] + UnknownPlugin { + /// Plugin name. + plugin: String, + /// Available plugins. + available: String, + }, + + /// Unknown permission. + #[error("unknown permission {permission} for plugin {plugin}")] + UnknownPermission { + /// Plugin name. + plugin: String, + + /// Permission identifier. + permission: String, + }, } /// Allowed and denied commands inside a permission. diff --git a/core/tauri-utils/src/acl/plugin.rs b/core/tauri-utils/src/acl/plugin.rs index e4291449f3a0..ff50540a72be 100644 --- a/core/tauri-utils/src/acl/plugin.rs +++ b/core/tauri-utils/src/acl/plugin.rs @@ -6,7 +6,7 @@ use std::collections::HashMap; -use super::{Permission, PermissionSet}; +use super::{build::PermissionFile, Permission, PermissionSet}; use serde::{Deserialize, Serialize}; /// Plugin manifest. @@ -19,3 +19,53 @@ pub struct Manifest { /// Plugin permission sets. pub permission_sets: HashMap, } + +impl Manifest { + /// Creates a new manifest from a list of permission files. + pub fn from_files(permission_files: Vec) -> Self { + let mut manifest = Self { + default_permission: None, + permissions: HashMap::new(), + permission_sets: HashMap::new(), + }; + + for permission_file in permission_files { + if let Some(default) = permission_file.default { + manifest.default_permission.replace(Permission { + identifier: "default".into(), + version: default.version, + description: default.description, + commands: default.commands, + scope: default.scope, + }); + } + + manifest.permissions.extend( + permission_file + .permission + .into_iter() + .map(|p| (p.identifier.clone(), p)) + .collect::>(), + ); + + manifest.permission_sets.extend( + permission_file + .set + .into_iter() + .map(|set| { + ( + set.identifier.clone(), + PermissionSet { + identifier: set.identifier, + description: set.description, + permissions: set.permissions, + }, + ) + }) + .collect::>(), + ); + } + + manifest + } +} diff --git a/core/tauri-utils/src/acl/resolved.rs b/core/tauri-utils/src/acl/resolved.rs index fc9d77957dd5..fb80cb7a3e02 100644 --- a/core/tauri-utils/src/acl/resolved.rs +++ b/core/tauri-utils/src/acl/resolved.rs @@ -4,9 +4,16 @@ //! Resolved ACL for runtime usage. -use std::collections::BTreeMap; +use std::{ + collections::{hash_map::DefaultHasher, BTreeMap}, + hash::{Hash, Hasher}, +}; -use super::{ExecutionContext, Value}; +use super::{ + capability::{Capability, CapabilityContext}, + plugin::Manifest, + Error, ExecutionContext, Permission, PermissionSet, Value, +}; /// A key for a scope, used to link a [`ResolvedCommand#structfield.scope`] to the store [`Resolved#structfield.scopes`]. pub type ScopeKey = usize; @@ -40,6 +47,7 @@ pub struct CommandKey { } /// Resolved access control list. +#[derive(Debug)] pub struct Resolved { /// The commands that are allowed. Map each command with its context to a [`ResolvedCommand`]. pub allowed_commands: BTreeMap, @@ -51,6 +59,219 @@ pub struct Resolved { pub global_scope: ResolvedScope, } +impl Resolved { + /// Resolves the ACL for the given plugin permissions and app capabilities. + pub fn resolve( + acl: BTreeMap, + capabilities: BTreeMap, + ) -> Result { + let mut allowed_commands = BTreeMap::new(); + let mut denied_commands = BTreeMap::new(); + + let mut current_scope_id = 0; + let mut command_scopes = BTreeMap::new(); + let mut global_scope = Vec::new(); + + // resolve commands + for capability in capabilities.values() { + for permission_id in &capability.permissions { + let permission_name = permission_id.get_base(); + + if let Some(plugin_name) = permission_id.get_prefix() { + let permissions = get_permissions(plugin_name, permission_name, &acl)?; + + for permission in permissions { + if permission.commands.allow.is_empty() && permission.commands.deny.is_empty() { + // global scope + global_scope.push(permission.scope.clone()); + } else { + current_scope_id += 1; + command_scopes.insert(current_scope_id, permission.scope.clone()); + + for allowed_command in &permission.commands.allow { + resolve_command( + &mut allowed_commands, + format!("plugin:{plugin_name}|{allowed_command}"), + capability, + current_scope_id, + ); + } + + for denied_command in &permission.commands.deny { + resolve_command( + &mut denied_commands, + format!("plugin:{plugin_name}|{denied_command}"), + capability, + current_scope_id, + ); + } + } + } + } + } + } + + // resolve scopes + let mut resolved_scopes = BTreeMap::new(); + + for allowed in allowed_commands.values_mut() { + allowed.scope.sort(); + + let mut hasher = DefaultHasher::new(); + allowed.scope.hash(&mut hasher); + let hash = hasher.finish() as usize; + + allowed.resolved_scope_key = hash; + + let resolved_scope = ResolvedScope { + allow: allowed + .scope + .iter() + .flat_map(|s| command_scopes.get(s).unwrap().allow.clone()) + .collect(), + deny: allowed + .scope + .iter() + .flat_map(|s| command_scopes.get(s).unwrap().deny.clone()) + .collect(), + }; + + resolved_scopes.insert(hash, resolved_scope); + } + + let global_scope = ResolvedScope { + allow: global_scope + .iter_mut() + .flat_map(|s| s.allow.take()) + .collect(), + deny: global_scope + .iter_mut() + .flat_map(|s| s.deny.take()) + .collect(), + }; + + let resolved = Self { + allowed_commands: allowed_commands + .into_iter() + .map(|(key, cmd)| { + ( + key, + ResolvedCommand { + windows: cmd.windows, + scope: cmd.resolved_scope_key, + }, + ) + }) + .collect(), + denied_commands: denied_commands + .into_iter() + .map(|(key, cmd)| { + ( + key, + ResolvedCommand { + windows: cmd.windows, + scope: cmd.resolved_scope_key, + }, + ) + }) + .collect(), + command_scope: resolved_scopes, + global_scope, + }; + + Ok(resolved) + } +} + +#[derive(Debug, Default)] +struct ResolvedCommandTemp { + pub windows: Vec, + pub scope: Vec, + pub resolved_scope_key: usize, +} + +fn resolve_command( + commands: &mut BTreeMap, + command: String, + capability: &Capability, + scope_id: usize, +) { + let contexts = match &capability.context { + CapabilityContext::Local => { + vec![ExecutionContext::Local] + } + CapabilityContext::Remote { dangerous_remote } => dangerous_remote + .iter() + .map(|domain| ExecutionContext::Remote { + domain: domain.to_string(), + }) + .collect(), + }; + + for context in contexts { + let resolved = commands + .entry(CommandKey { + name: command.clone(), + context, + }) + .or_default(); + + resolved.windows.extend(capability.windows.clone()); + resolved.scope.push(scope_id); + } +} + +// get the permissions from a permission set +fn get_permission_set_permissions<'a>( + manifest: &'a Manifest, + set: &'a PermissionSet, +) -> Result, Error> { + let mut permissions = Vec::new(); + + for p in &set.permissions { + if let Some(permission) = manifest.permissions.get(p) { + permissions.push(permission); + } else if let Some(permission_set) = manifest.permission_sets.get(p) { + permissions.extend(get_permission_set_permissions(manifest, permission_set)?); + } else { + return Err(Error::SetPermissionNotFound { + permission: p.to_string(), + set: set.identifier.clone(), + }); + } + } + + Ok(permissions) +} + +fn get_permissions<'a>( + plugin_name: &'a str, + permission_name: &'a str, + acl: &'a BTreeMap, +) -> Result, Error> { + let manifest = acl.get(plugin_name).ok_or_else(|| Error::UnknownPlugin { + plugin: plugin_name.to_string(), + available: acl.keys().cloned().collect::>().join(", "), + })?; + + if permission_name == "default" { + Ok(vec![manifest.default_permission.as_ref().ok_or_else( + || Error::MissingDefaultPermission { + plugin: plugin_name.to_string(), + }, + )?]) + } else if let Some(set) = manifest.permission_sets.get(permission_name) { + get_permission_set_permissions(manifest, set) + } else if let Some(permission) = manifest.permissions.get(permission_name) { + Ok(vec![permission]) + } else { + Err(Error::UnknownPermission { + plugin: plugin_name.to_string(), + permission: permission_name.to_string(), + }) + } +} + #[cfg(feature = "build")] mod build { use proc_macro2::TokenStream; diff --git a/core/tests/acl/Cargo.toml b/core/tests/acl/Cargo.toml new file mode 100644 index 000000000000..0fe970b9990d --- /dev/null +++ b/core/tests/acl/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "acl-tests" +version = "0.1.0" +authors.workspace = true +homepage.workspace = true +repository.workspace = true +categories.workspace = true +license.workspace = true +edition.workspace = true +rust-version.workspace = true +publish = false + +[dev-dependencies] +tauri-utils = { path = "../../tauri-utils/", features = ["build"] } +serde_json = "1" +insta = "1" diff --git a/core/tests/acl/fixtures/capabilities/basic-ping/cap.toml b/core/tests/acl/fixtures/capabilities/basic-ping/cap.toml new file mode 100644 index 000000000000..95755ed0f73d --- /dev/null +++ b/core/tests/acl/fixtures/capabilities/basic-ping/cap.toml @@ -0,0 +1,4 @@ +identifier = "run-app" +description = "app capability" +windows = ["main"] +permissions = ["ping:allow-ping"] diff --git a/core/tests/acl/fixtures/capabilities/basic-ping/required-plugins.json b/core/tests/acl/fixtures/capabilities/basic-ping/required-plugins.json new file mode 100644 index 000000000000..4239d5ee3abd --- /dev/null +++ b/core/tests/acl/fixtures/capabilities/basic-ping/required-plugins.json @@ -0,0 +1 @@ +["ping"] diff --git a/core/tests/acl/fixtures/plugins/ping/ping.toml b/core/tests/acl/fixtures/plugins/ping/ping.toml new file mode 100644 index 000000000000..0fc49a7a2432 --- /dev/null +++ b/core/tests/acl/fixtures/plugins/ping/ping.toml @@ -0,0 +1,9 @@ +[[permission]] +identifier = "allow-ping" +description = "Enables the ping command without any pre-configured scope." +commands.allow = ["ping"] + +[[permission]] +identifier = "deny-ping" +description = "Denies the ping command without any pre-configured scope." +commands.deny = ["ping"] diff --git a/core/tests/acl/fixtures/snapshots/acl_tests__tests__basic-ping.snap b/core/tests/acl/fixtures/snapshots/acl_tests__tests__basic-ping.snap new file mode 100644 index 000000000000..bb7ebced63cb --- /dev/null +++ b/core/tests/acl/fixtures/snapshots/acl_tests__tests__basic-ping.snap @@ -0,0 +1,29 @@ +--- +source: core/tests/acl/src/lib.rs +assertion_line: 49 +expression: resolved +--- +Resolved { + allowed_commands: { + CommandKey { + name: "plugin:ping|ping", + context: Local, + }: ResolvedCommand { + windows: [ + "main", + ], + scope: 7912899488978770657, + }, + }, + denied_commands: {}, + command_scope: { + 7912899488978770657: ResolvedScope { + allow: [], + deny: [], + }, + }, + global_scope: ResolvedScope { + allow: [], + deny: [], + }, +} diff --git a/core/tests/acl/src/lib.rs b/core/tests/acl/src/lib.rs new file mode 100644 index 000000000000..b030b2af51b4 --- /dev/null +++ b/core/tests/acl/src/lib.rs @@ -0,0 +1,60 @@ +#[cfg(test)] +mod tests { + use std::{ + collections::BTreeMap, + fs::{read_dir, read_to_string}, + path::Path, + }; + + use tauri_utils::acl::{build::parse_capabilities, plugin::Manifest, resolved::Resolved}; + + fn load_plugins(plugins: &[String]) -> BTreeMap { + let mut manifests = BTreeMap::new(); + + let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); + for plugin in plugins { + let plugin_path = manifest_dir.join("fixtures").join("plugins").join(plugin); + + let permission_files = + tauri_utils::acl::build::define_permissions(&format!("{}/*.toml", plugin_path.display())) + .expect("failed to define permissions"); + let manifest = Manifest::from_files(permission_files); + manifests.insert(plugin.to_string(), manifest); + } + + manifests + } + + #[test] + fn resolve_acl() { + let mut settings = insta::Settings::clone_current(); + settings.set_snapshot_path("../fixtures/snapshots"); + let _guard = settings.bind_to_scope(); + + let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); + let fixtures_path = manifest_dir.join("fixtures").join("capabilities"); + for fixture_path in read_dir(&fixtures_path).expect("failed to read fixtures") { + let fixture_entry = fixture_path.expect("failed to read fixture entry"); + let fixture_plugins_str = read_to_string(fixture_entry.path().join("required-plugins.json")) + .expect("failed to read fixture required-plugins.json file"); + let fixture_plugins: Vec = serde_json::from_str(&fixture_plugins_str) + .expect("required-plugins.json is not a valid JSON"); + + let manifests = load_plugins(&fixture_plugins); + let capabilities = parse_capabilities(&format!("{}/*.toml", fixture_entry.path().display())) + .expect("failed to parse capabilities"); + + let resolved = Resolved::resolve(manifests, capabilities).expect("failed to resolve ACL"); + + insta::assert_debug_snapshot!( + fixture_entry + .path() + .file_name() + .unwrap() + .to_string_lossy() + .to_string(), + resolved + ); + } + } +} From dd94e8cb55da8c3d29edefaab281c661745edeed Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Tue, 16 Jan 2024 14:34:51 -0300 Subject: [PATCH 36/69] fixture for permission set [skip ci] --- .../capabilities/file-explorer/cap.toml | 4 ++ .../file-explorer/required-plugins.json | 1 + .../acl/fixtures/plugins/fs/read-dir.toml | 4 ++ .../acl/fixtures/plugins/fs/read-file.toml | 4 ++ core/tests/acl/fixtures/plugins/fs/read.toml | 4 ++ core/tests/acl/fixtures/plugins/fs/scope.toml | 6 +++ .../tests/acl/fixtures/plugins/ping/ping.toml | 5 -- .../acl_tests__tests__file-explorer.snap | 50 +++++++++++++++++++ 8 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 core/tests/acl/fixtures/capabilities/file-explorer/cap.toml create mode 100644 core/tests/acl/fixtures/capabilities/file-explorer/required-plugins.json create mode 100644 core/tests/acl/fixtures/plugins/fs/read-dir.toml create mode 100644 core/tests/acl/fixtures/plugins/fs/read-file.toml create mode 100644 core/tests/acl/fixtures/plugins/fs/read.toml create mode 100644 core/tests/acl/fixtures/plugins/fs/scope.toml create mode 100644 core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer.snap diff --git a/core/tests/acl/fixtures/capabilities/file-explorer/cap.toml b/core/tests/acl/fixtures/capabilities/file-explorer/cap.toml new file mode 100644 index 000000000000..e76764f72706 --- /dev/null +++ b/core/tests/acl/fixtures/capabilities/file-explorer/cap.toml @@ -0,0 +1,4 @@ +identifier = "run-app" +description = "app capability" +windows = ["main"] +permissions = ["fs:read", "fs:allow-app"] diff --git a/core/tests/acl/fixtures/capabilities/file-explorer/required-plugins.json b/core/tests/acl/fixtures/capabilities/file-explorer/required-plugins.json new file mode 100644 index 000000000000..9ab323181acf --- /dev/null +++ b/core/tests/acl/fixtures/capabilities/file-explorer/required-plugins.json @@ -0,0 +1 @@ +["fs"] diff --git a/core/tests/acl/fixtures/plugins/fs/read-dir.toml b/core/tests/acl/fixtures/plugins/fs/read-dir.toml new file mode 100644 index 000000000000..05c3452b2368 --- /dev/null +++ b/core/tests/acl/fixtures/plugins/fs/read-dir.toml @@ -0,0 +1,4 @@ +[[permission]] +identifier = "allow-read-dir" +description = "Enables the read_dir command without any pre-configured scope." +commands.allow = ["read_dir"] diff --git a/core/tests/acl/fixtures/plugins/fs/read-file.toml b/core/tests/acl/fixtures/plugins/fs/read-file.toml new file mode 100644 index 000000000000..c2b37b40938e --- /dev/null +++ b/core/tests/acl/fixtures/plugins/fs/read-file.toml @@ -0,0 +1,4 @@ +[[permission]] +identifier = "allow-read-file" +description = "Enables the read_file command without any pre-configured scope." +commands.allow = ["read_file"] diff --git a/core/tests/acl/fixtures/plugins/fs/read.toml b/core/tests/acl/fixtures/plugins/fs/read.toml new file mode 100644 index 000000000000..ab9c72c61c45 --- /dev/null +++ b/core/tests/acl/fixtures/plugins/fs/read.toml @@ -0,0 +1,4 @@ +[[set]] +identifier = "read" +description = "allows all read APIs" +permissions = ["allow-read-dir", "allow-read-file"] diff --git a/core/tests/acl/fixtures/plugins/fs/scope.toml b/core/tests/acl/fixtures/plugins/fs/scope.toml new file mode 100644 index 000000000000..921b2e91eca6 --- /dev/null +++ b/core/tests/acl/fixtures/plugins/fs/scope.toml @@ -0,0 +1,6 @@ + +[[permission]] +identifier = "allow-app" +description = "Allows accessing the $APP path." +[permission.scope.allow] +path = "$APP" diff --git a/core/tests/acl/fixtures/plugins/ping/ping.toml b/core/tests/acl/fixtures/plugins/ping/ping.toml index 0fc49a7a2432..dfd151dddf11 100644 --- a/core/tests/acl/fixtures/plugins/ping/ping.toml +++ b/core/tests/acl/fixtures/plugins/ping/ping.toml @@ -2,8 +2,3 @@ identifier = "allow-ping" description = "Enables the ping command without any pre-configured scope." commands.allow = ["ping"] - -[[permission]] -identifier = "deny-ping" -description = "Denies the ping command without any pre-configured scope." -commands.deny = ["ping"] diff --git a/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer.snap b/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer.snap new file mode 100644 index 000000000000..f17c6a45da68 --- /dev/null +++ b/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer.snap @@ -0,0 +1,50 @@ +--- +source: core/tests/acl/src/lib.rs +assertion_line: 49 +expression: resolved +--- +Resolved { + allowed_commands: { + CommandKey { + name: "plugin:fs|read_dir", + context: Local, + }: ResolvedCommand { + windows: [ + "main", + ], + scope: 7912899488978770657, + }, + CommandKey { + name: "plugin:fs|read_file", + context: Local, + }: ResolvedCommand { + windows: [ + "main", + ], + scope: 18088007599891946824, + }, + }, + denied_commands: {}, + command_scope: { + 7912899488978770657: ResolvedScope { + allow: [], + deny: [], + }, + 18088007599891946824: ResolvedScope { + allow: [], + deny: [], + }, + }, + global_scope: ResolvedScope { + allow: [ + Map( + { + "path": String( + "$APP", + ), + }, + ), + ], + deny: [], + }, +} From fbd016d7871ed475d3ca3f1fb4dd0379feb476b7 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Tue, 16 Jan 2024 14:40:21 -0300 Subject: [PATCH 37/69] remote context test and small fix[skip ci] --- core/tauri-utils/src/acl/capability.rs | 5 +- core/tauri-utils/src/acl/resolved.rs | 2 +- .../file-explorer-remote/cap.toml | 6 +++ .../required-plugins.json | 1 + ...cl_tests__tests__file-explorer-remote.snap | 54 +++++++++++++++++++ 5 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 core/tests/acl/fixtures/capabilities/file-explorer-remote/cap.toml create mode 100644 core/tests/acl/fixtures/capabilities/file-explorer-remote/required-plugins.json create mode 100644 core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer-remote.snap diff --git a/core/tauri-utils/src/acl/capability.rs b/core/tauri-utils/src/acl/capability.rs index fe037c5c03ee..9a01b5d3c2d4 100644 --- a/core/tauri-utils/src/acl/capability.rs +++ b/core/tauri-utils/src/acl/capability.rs @@ -42,13 +42,14 @@ pub struct Capability { /// Context of 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 domain this capability refers to. - dangerous_remote: Vec, + /// Remote domains this capability refers to. + domains: Vec, }, } diff --git a/core/tauri-utils/src/acl/resolved.rs b/core/tauri-utils/src/acl/resolved.rs index fb80cb7a3e02..0519155c37c8 100644 --- a/core/tauri-utils/src/acl/resolved.rs +++ b/core/tauri-utils/src/acl/resolved.rs @@ -200,7 +200,7 @@ fn resolve_command( CapabilityContext::Local => { vec![ExecutionContext::Local] } - CapabilityContext::Remote { dangerous_remote } => dangerous_remote + CapabilityContext::Remote { domains } => domains .iter() .map(|domain| ExecutionContext::Remote { domain: domain.to_string(), diff --git a/core/tests/acl/fixtures/capabilities/file-explorer-remote/cap.toml b/core/tests/acl/fixtures/capabilities/file-explorer-remote/cap.toml new file mode 100644 index 000000000000..ebc8353d3d1f --- /dev/null +++ b/core/tests/acl/fixtures/capabilities/file-explorer-remote/cap.toml @@ -0,0 +1,6 @@ +identifier = "run-app" +description = "app capability" +windows = ["main"] +permissions = ["fs:read", "fs:allow-app"] +[context.remote] +domains = ["tauri.app"] diff --git a/core/tests/acl/fixtures/capabilities/file-explorer-remote/required-plugins.json b/core/tests/acl/fixtures/capabilities/file-explorer-remote/required-plugins.json new file mode 100644 index 000000000000..9ab323181acf --- /dev/null +++ b/core/tests/acl/fixtures/capabilities/file-explorer-remote/required-plugins.json @@ -0,0 +1 @@ +["fs"] diff --git a/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer-remote.snap b/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer-remote.snap new file mode 100644 index 000000000000..8f1cf1a82d39 --- /dev/null +++ b/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer-remote.snap @@ -0,0 +1,54 @@ +--- +source: core/tests/acl/src/lib.rs +assertion_line: 49 +expression: resolved +--- +Resolved { + allowed_commands: { + CommandKey { + name: "plugin:fs|read_dir", + context: Remote { + domain: "tauri.app", + }, + }: ResolvedCommand { + windows: [ + "main", + ], + scope: 7912899488978770657, + }, + CommandKey { + name: "plugin:fs|read_file", + context: Remote { + domain: "tauri.app", + }, + }: ResolvedCommand { + windows: [ + "main", + ], + scope: 18088007599891946824, + }, + }, + denied_commands: {}, + command_scope: { + 7912899488978770657: ResolvedScope { + allow: [], + deny: [], + }, + 18088007599891946824: ResolvedScope { + allow: [], + deny: [], + }, + }, + global_scope: ResolvedScope { + allow: [ + Map( + { + "path": String( + "$APP", + ), + }, + ), + ], + deny: [], + }, +} From 1338579372cfd80808658270e99ddde4e732c290 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Tue, 16 Jan 2024 14:48:45 -0300 Subject: [PATCH 38/69] ignore empty scope [skip ci] --- core/tauri-utils/src/acl/resolved.rs | 73 +++++++++++-------- core/tauri/src/command/authority.rs | 5 +- core/tauri/src/scope/ipc.rs | 4 +- .../acl_tests__tests__basic-ping.snap | 10 +-- ...cl_tests__tests__file-explorer-remote.snap | 16 +--- .../acl_tests__tests__file-explorer.snap | 16 +--- 6 files changed, 56 insertions(+), 68 deletions(-) diff --git a/core/tauri-utils/src/acl/resolved.rs b/core/tauri-utils/src/acl/resolved.rs index 0519155c37c8..6428dc1e633f 100644 --- a/core/tauri-utils/src/acl/resolved.rs +++ b/core/tauri-utils/src/acl/resolved.rs @@ -24,7 +24,7 @@ pub struct ResolvedCommand { /// The list of window label patterns that is allowed to run this command. pub windows: Vec, /// The reference of the scope that is associated with this command. See [`Resolved#structfield.scopes`]. - pub scope: ScopeKey, + pub scope: Option, } /// A resolved scope. Merges all scopes defined for a single command. @@ -85,15 +85,24 @@ impl Resolved { // global scope global_scope.push(permission.scope.clone()); } else { - current_scope_id += 1; - command_scopes.insert(current_scope_id, permission.scope.clone()); + let has_scope = permission.scope.allow.is_some() || permission.scope.deny.is_some(); + if has_scope { + current_scope_id += 1; + command_scopes.insert(current_scope_id, permission.scope.clone()); + } + + let scope_id = if has_scope { + Some(current_scope_id) + } else { + None + }; for allowed_command in &permission.commands.allow { resolve_command( &mut allowed_commands, format!("plugin:{plugin_name}|{allowed_command}"), capability, - current_scope_id, + scope_id, ); } @@ -102,7 +111,7 @@ impl Resolved { &mut denied_commands, format!("plugin:{plugin_name}|{denied_command}"), capability, - current_scope_id, + scope_id, ); } } @@ -115,28 +124,30 @@ impl Resolved { let mut resolved_scopes = BTreeMap::new(); for allowed in allowed_commands.values_mut() { - allowed.scope.sort(); - - let mut hasher = DefaultHasher::new(); - allowed.scope.hash(&mut hasher); - let hash = hasher.finish() as usize; - - allowed.resolved_scope_key = hash; - - let resolved_scope = ResolvedScope { - allow: allowed - .scope - .iter() - .flat_map(|s| command_scopes.get(s).unwrap().allow.clone()) - .collect(), - deny: allowed - .scope - .iter() - .flat_map(|s| command_scopes.get(s).unwrap().deny.clone()) - .collect(), - }; - - resolved_scopes.insert(hash, resolved_scope); + if !allowed.scope.is_empty() { + allowed.scope.sort(); + + let mut hasher = DefaultHasher::new(); + allowed.scope.hash(&mut hasher); + let hash = hasher.finish() as usize; + + allowed.resolved_scope_key.replace(hash); + + let resolved_scope = ResolvedScope { + allow: allowed + .scope + .iter() + .flat_map(|s| command_scopes.get(s).unwrap().allow.clone()) + .collect(), + deny: allowed + .scope + .iter() + .flat_map(|s| command_scopes.get(s).unwrap().deny.clone()) + .collect(), + }; + + resolved_scopes.insert(hash, resolved_scope); + } } let global_scope = ResolvedScope { @@ -187,14 +198,14 @@ impl Resolved { struct ResolvedCommandTemp { pub windows: Vec, pub scope: Vec, - pub resolved_scope_key: usize, + pub resolved_scope_key: Option, } fn resolve_command( commands: &mut BTreeMap, command: String, capability: &Capability, - scope_id: usize, + scope_id: Option, ) { let contexts = match &capability.context { CapabilityContext::Local => { @@ -217,7 +228,9 @@ fn resolve_command( .or_default(); resolved.windows.extend(capability.windows.clone()); - resolved.scope.push(scope_id); + if let Some(id) = scope_id { + resolved.scope.push(id); + } } } diff --git a/core/tauri/src/command/authority.rs b/core/tauri/src/command/authority.rs index 4eb959331211..b53e6daff725 100644 --- a/core/tauri/src/command/authority.rs +++ b/core/tauri/src/command/authority.rs @@ -95,14 +95,15 @@ impl<'a, R: Runtime, T: Debug + DeserializeOwned + Send + Sync + 'static> Comman command .acl .as_ref() - .and_then(|resolved| { + .and_then(|resolved| resolved.scope) + .and_then(|scope_id| { command .message .window .manager .runtime_authority .scope_manager - .get_command_scope_typed(&resolved.scope) + .get_command_scope_typed(&scope_id) .map(CommandScope) }) .ok_or_else(|| InvokeError::from_anyhow(anyhow::anyhow!("scope not found"))) diff --git a/core/tauri/src/scope/ipc.rs b/core/tauri/src/scope/ipc.rs index e147c5bcd041..faee2cc36725 100644 --- a/core/tauri/src/scope/ipc.rs +++ b/core/tauri/src/scope/ipc.rs @@ -194,7 +194,7 @@ mod tests { }, ResolvedCommand { windows: vec!["main".into()], - scope: 0, + scope: None, }, ); for scope in &scopes { @@ -207,7 +207,7 @@ mod tests { }, ResolvedCommand { windows: vec!["main".into()], - scope: 0, + scope: None, }, ); } diff --git a/core/tests/acl/fixtures/snapshots/acl_tests__tests__basic-ping.snap b/core/tests/acl/fixtures/snapshots/acl_tests__tests__basic-ping.snap index bb7ebced63cb..51d739424052 100644 --- a/core/tests/acl/fixtures/snapshots/acl_tests__tests__basic-ping.snap +++ b/core/tests/acl/fixtures/snapshots/acl_tests__tests__basic-ping.snap @@ -1,6 +1,5 @@ --- source: core/tests/acl/src/lib.rs -assertion_line: 49 expression: resolved --- Resolved { @@ -12,16 +11,11 @@ Resolved { windows: [ "main", ], - scope: 7912899488978770657, + scope: None, }, }, denied_commands: {}, - command_scope: { - 7912899488978770657: ResolvedScope { - allow: [], - deny: [], - }, - }, + command_scope: {}, global_scope: ResolvedScope { allow: [], deny: [], diff --git a/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer-remote.snap b/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer-remote.snap index 8f1cf1a82d39..d56cf57dee71 100644 --- a/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer-remote.snap +++ b/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer-remote.snap @@ -1,6 +1,5 @@ --- source: core/tests/acl/src/lib.rs -assertion_line: 49 expression: resolved --- Resolved { @@ -14,7 +13,7 @@ Resolved { windows: [ "main", ], - scope: 7912899488978770657, + scope: None, }, CommandKey { name: "plugin:fs|read_file", @@ -25,20 +24,11 @@ Resolved { windows: [ "main", ], - scope: 18088007599891946824, + scope: None, }, }, denied_commands: {}, - command_scope: { - 7912899488978770657: ResolvedScope { - allow: [], - deny: [], - }, - 18088007599891946824: ResolvedScope { - allow: [], - deny: [], - }, - }, + command_scope: {}, global_scope: ResolvedScope { allow: [ Map( diff --git a/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer.snap b/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer.snap index f17c6a45da68..a0382179e6c4 100644 --- a/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer.snap +++ b/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer.snap @@ -1,6 +1,5 @@ --- source: core/tests/acl/src/lib.rs -assertion_line: 49 expression: resolved --- Resolved { @@ -12,7 +11,7 @@ Resolved { windows: [ "main", ], - scope: 7912899488978770657, + scope: None, }, CommandKey { name: "plugin:fs|read_file", @@ -21,20 +20,11 @@ Resolved { windows: [ "main", ], - scope: 18088007599891946824, + scope: None, }, }, denied_commands: {}, - command_scope: { - 7912899488978770657: ResolvedScope { - allow: [], - deny: [], - }, - 18088007599891946824: ResolvedScope { - allow: [], - deny: [], - }, - }, + command_scope: {}, global_scope: ResolvedScope { allow: [ Map( From 6fba15bbe59adc25ffc9170f8d8a06e07ca48a2d Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 17 Jan 2024 09:04:14 -0300 Subject: [PATCH 39/69] code review [skip ci] --- core/tauri-plugin/Cargo.toml | 1 + core/tauri-plugin/src/build/mod.rs | 4 ++-- core/tauri-utils/src/acl/mod.rs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/core/tauri-plugin/Cargo.toml b/core/tauri-plugin/Cargo.toml index 1823939132fe..5a3efb8df292 100644 --- a/core/tauri-plugin/Cargo.toml +++ b/core/tauri-plugin/Cargo.toml @@ -18,6 +18,7 @@ build = [ "dep:toml", "dep:schemars", ] +runtime = [] [dependencies] serde = { version = "1", optional = true } diff --git a/core/tauri-plugin/src/build/mod.rs b/core/tauri-plugin/src/build/mod.rs index ec5073962225..6283b27df679 100644 --- a/core/tauri-plugin/src/build/mod.rs +++ b/core/tauri-plugin/src/build/mod.rs @@ -101,8 +101,8 @@ commands.deny = ["{command}"] } /// Grab an env var that is expected to be set inside of build scripts. -fn build_var(key: &str) -> Result { - std::env::var(key).map_err(|_| Error::BuildVar(key.into())) +fn build_var(key: &'static str) -> Result { + std::env::var(key).map_err(|_| Error::BuildVar(key)) } fn find_metadata() -> Result { diff --git a/core/tauri-utils/src/acl/mod.rs b/core/tauri-utils/src/acl/mod.rs index 569764336069..cfa4442f7b5f 100644 --- a/core/tauri-utils/src/acl/mod.rs +++ b/core/tauri-utils/src/acl/mod.rs @@ -25,7 +25,7 @@ pub enum Error { /// /// Whatever generated this should be called inside of a build script. #[error("expected build script env var {0}, but it was not found - ensure this is called in a build script")] - BuildVar(String), + BuildVar(&'static str), /// Plugin name doesn't follow Tauri standards #[error("plugin names cannot contain underscores")] From 3868add4a3aae8ebb4229e6be3e57294643d6cb6 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 17 Jan 2024 09:06:29 -0300 Subject: [PATCH 40/69] lint [skip ci] --- core/tauri/src/app.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/core/tauri/src/app.rs b/core/tauri/src/app.rs index 92f2791871ed..526b405a021a 100644 --- a/core/tauri/src/app.rs +++ b/core/tauri/src/app.rs @@ -48,7 +48,7 @@ use std::{ borrow::Cow, collections::HashMap, fmt, - sync::{mpsc::Sender, Arc, Weak}, + sync::{mpsc::Sender, Arc}, }; use crate::runtime::RuntimeHandle; @@ -256,7 +256,7 @@ impl AppHandle { >( &self, f: F, - ) -> crate::Result> { + ) -> crate::Result> { self.runtime_handle.create_tao_window(f).map_err(Into::into) } @@ -983,10 +983,8 @@ struct InvokeInitializationScript<'a> { fetch_channel_data_command: &'a str, use_custom_protocol: bool, } - -impl Builder { - /// Creates a new App builder. - pub fn new() -> Self { +impl Default for Builder { + fn default() -> Self { Self { #[cfg(any(windows, target_os = "linux"))] runtime_any_thread: false, @@ -1014,7 +1012,16 @@ impl Builder { device_event_filter: Default::default(), } } +} + +impl Builder { + /// Creates a new App builder. + pub fn new() -> Self { + Self::default() + } +} +impl Builder { /// Builds a new Tauri application running on any thread, bypassing the main thread requirement. /// /// ## Platform-specific @@ -1828,14 +1835,7 @@ fn on_event_loop_event, RunEvent) + 'static>( } } -/// Make `Wry` the default `Runtime` for `Builder` -#[cfg(feature = "wry")] -#[cfg_attr(docsrs, doc(cfg(feature = "wry")))] -impl Default for Builder { - fn default() -> Self { - Self::new() - } -} + #[cfg(test)] mod tests { From 93257db982bffd8d66bc01f2e0180d05f11e1ed3 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 17 Jan 2024 09:35:04 -0300 Subject: [PATCH 41/69] runtime fixes --- core/tauri-plugin/Cargo.toml | 6 +-- core/tauri-utils/src/acl/build.rs | 55 +--------------------------- core/tauri-utils/src/acl/plugin.rs | 44 +++++++++++++++++++++- core/tauri-utils/src/acl/resolved.rs | 2 +- core/tauri/src/app.rs | 28 +++++++++----- examples/api/src-tauri/Cargo.lock | 19 +++++----- 6 files changed, 73 insertions(+), 81 deletions(-) diff --git a/core/tauri-plugin/Cargo.toml b/core/tauri-plugin/Cargo.toml index 5a3efb8df292..fe9c57d60286 100644 --- a/core/tauri-plugin/Cargo.toml +++ b/core/tauri-plugin/Cargo.toml @@ -16,21 +16,17 @@ build = [ "dep:serde_json", "dep:glob", "dep:toml", - "dep:schemars", ] runtime = [] [dependencies] serde = { version = "1", optional = true } cargo_metadata = { version = "0.18", optional = true } -tauri-utils = { version = "2.0.0-alpha.12", default-features = false, path = "../tauri-utils", features = [ - #"schema", -] } +tauri-utils = { version = "2.0.0-alpha.12", default-features = false, path = "../tauri-utils" } tauri = { version = "2.0.0-alpha.20", default-features = false, path = "../tauri" } serde_json = { version = "1", optional = true } glob = { version = "0.3", optional = true } toml = { version = "0.8", optional = true } -schemars = { version = "0.8", optional = true } [package.metadata.docs.rs] features = ["build", "runtime"] diff --git a/core/tauri-utils/src/acl/build.rs b/core/tauri-utils/src/acl/build.rs index 446cf1634a75..df13049022b9 100644 --- a/core/tauri-utils/src/acl/build.rs +++ b/core/tauri-utils/src/acl/build.rs @@ -9,19 +9,17 @@ use std::{ env::vars_os, fs::File, io::{BufWriter, Write}, - num::NonZeroU64, path::PathBuf, }; use crate::acl::Error; -use crate::acl::{Commands, Permission, Scopes}; use schemars::{ schema::{InstanceType, Metadata, RootSchema, Schema, SchemaObject, SubschemaValidation}, schema_for, }; use serde::Deserialize; -use super::capability::Capability; +use super::{capability::Capability, plugin::PermissionFile}; /// Cargo cfg key for permissions file paths pub const PERMISSION_FILES_PATH_KEY: &str = "PERMISSION_FILES_PATH"; @@ -38,57 +36,6 @@ const CAPABILITY_FILE_EXTENSIONS: &[&str] = &["json", "toml"]; /// Known filename of a capability schema const CAPABILITIES_SCHEMA_FILE_NAME: &str = ".schema.json"; -/// A set of permissions or other permission sets. -#[derive(Debug, Deserialize, schemars::JsonSchema)] -pub struct PermissionSet { - /// A unique identifier for the permission. - pub identifier: String, - - /// Human-readable description of what the permission does. - pub description: String, - - /// All permissions this set contains. - pub permissions: Vec, -} - -/// The default permission of the plugin. -/// -/// Works similarly to a permission with the "default" identifier. -#[derive(Debug, Deserialize, schemars::JsonSchema)] -pub struct DefaultPermission { - /// The version of the permission. - pub version: Option, - - /// Human-readable description of what the permission does. - pub description: Option, - - /// Allowed or denied commands when using this permission. - #[serde(default)] - pub commands: Commands, - - /// Allowed or denied scoped when using this permission. - #[serde(default)] - pub scope: Scopes, -} - -/// Permission file that can define a default permission, a set of permissions or a list of inlined permissions. -#[derive(Debug, Deserialize, schemars::JsonSchema)] -pub struct PermissionFile { - /// The default permission set for the plugin - pub default: Option, - - /// A list of permissions sets defined - #[serde(default)] - pub set: Vec, - - /// Test something!! - pub test: Option, - - /// A list of inlined permissions - #[serde(default)] - pub permission: Vec, -} - /// Capability formats accepted in a capability file. #[derive(Deserialize, schemars::JsonSchema)] #[serde(untagged)] diff --git a/core/tauri-utils/src/acl/plugin.rs b/core/tauri-utils/src/acl/plugin.rs index ff50540a72be..816406a23808 100644 --- a/core/tauri-utils/src/acl/plugin.rs +++ b/core/tauri-utils/src/acl/plugin.rs @@ -4,11 +4,51 @@ //! Plugin ACL types. -use std::collections::HashMap; +use std::{collections::HashMap, num::NonZeroU64}; -use super::{build::PermissionFile, Permission, PermissionSet}; +use super::{Commands, Permission, PermissionSet, Scopes}; use serde::{Deserialize, Serialize}; +/// The default permission of the plugin. +/// +/// Works similarly to a permission with the "default" identifier. +#[derive(Debug, Deserialize)] +#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] +pub struct DefaultPermission { + /// The version of the permission. + pub version: Option, + + /// Human-readable description of what the permission does. + pub description: Option, + + /// Allowed or denied commands when using this permission. + #[serde(default)] + pub commands: Commands, + + /// Allowed or denied scoped when using this permission. + #[serde(default)] + pub scope: Scopes, +} + +/// Permission file that can define a default permission, a set of permissions or a list of inlined permissions. +#[derive(Debug, Deserialize)] +#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] +pub struct PermissionFile { + /// The default permission set for the plugin + pub default: Option, + + /// A list of permissions sets defined + #[serde(default)] + pub set: Vec, + + /// Test something!! + pub test: Option, + + /// A list of inlined permissions + #[serde(default)] + pub permission: Vec, +} + /// Plugin manifest. #[derive(Serialize, Deserialize)] pub struct Manifest { diff --git a/core/tauri-utils/src/acl/resolved.rs b/core/tauri-utils/src/acl/resolved.rs index 6428dc1e633f..bee6e357d9ff 100644 --- a/core/tauri-utils/src/acl/resolved.rs +++ b/core/tauri-utils/src/acl/resolved.rs @@ -318,7 +318,7 @@ mod build { impl ToTokens for ResolvedCommand { fn to_tokens(&self, tokens: &mut TokenStream) { let windows = vec_lit(&self.windows, str_lit); - let scope = self.scope; + let scope = opt_lit(self.scope.as_ref()); literal_struct!(tokens, ResolvedCommand, windows, scope) } } diff --git a/core/tauri/src/app.rs b/core/tauri/src/app.rs index 828a842d20be..a5158d5c8ac8 100644 --- a/core/tauri/src/app.rs +++ b/core/tauri/src/app.rs @@ -987,8 +987,27 @@ struct InvokeInitializationScript<'a> { fetch_channel_data_command: &'a str, use_custom_protocol: bool, } + +/// Make `Wry` the default `Runtime` for `Builder` +#[cfg(feature = "wry")] +#[cfg_attr(docsrs, doc(cfg(feature = "wry")))] +impl Default for Builder { + fn default() -> Self { + Self::new() + } +} + +#[cfg(not(feature = "wry"))] +#[cfg_attr(docsrs, doc(cfg(not(feature = "wry"))))] impl Default for Builder { fn default() -> Self { + Self::new() + } +} + +impl Builder { + /// Creates a new App builder. + pub fn new() -> Self { Self { #[cfg(any(windows, target_os = "linux"))] runtime_any_thread: false, @@ -1018,13 +1037,6 @@ impl Default for Builder { } } -impl Builder { - /// Creates a new App builder. - pub fn new() -> Self { - Self::default() - } -} - impl Builder { /// Builds a new Tauri application running on any thread, bypassing the main thread requirement. /// @@ -1840,8 +1852,6 @@ fn on_event_loop_event, RunEvent) + 'static>( } } - - #[cfg(test)] mod tests { #[test] diff --git a/examples/api/src-tauri/Cargo.lock b/examples/api/src-tauri/Cargo.lock index e469964a63bb..a03a6953651b 100644 --- a/examples/api/src-tauri/Cargo.lock +++ b/examples/api/src-tauri/Cargo.lock @@ -3493,7 +3493,7 @@ checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" [[package]] name = "tauri" -version = "2.0.0-alpha.20" +version = "2.0.0-alpha.21" dependencies = [ "anyhow", "bytes", @@ -3544,7 +3544,7 @@ dependencies = [ [[package]] name = "tauri-build" -version = "2.0.0-alpha.13" +version = "2.0.0-alpha.14" dependencies = [ "anyhow", "cargo_toml", @@ -3568,7 +3568,7 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "2.0.0-alpha.12" +version = "2.0.0-alpha.13" dependencies = [ "base64", "brotli", @@ -3592,7 +3592,7 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.0.0-alpha.12" +version = "2.0.0-alpha.13" dependencies = [ "heck", "proc-macro2", @@ -3608,7 +3608,6 @@ version = "0.1.0" dependencies = [ "cargo_metadata", "glob", - "schemars", "serde", "serde_json", "tauri", @@ -3643,7 +3642,7 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "1.0.0-alpha.7" +version = "1.0.0-alpha.8" dependencies = [ "gtk", "http", @@ -3659,7 +3658,7 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "1.0.0-alpha.8" +version = "1.0.0-alpha.9" dependencies = [ "cocoa", "gtk", @@ -3678,7 +3677,7 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "2.0.0-alpha.12" +version = "2.0.0-alpha.13" dependencies = [ "aes-gcm", "brotli", @@ -4711,9 +4710,9 @@ dependencies = [ [[package]] name = "wry" -version = "0.35.0" +version = "0.35.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "764ce8212721205a90c79f5fa04f5135af597bea9072f22a5e7f39dcd0669f2e" +checksum = "d3016c47c9b6f7029a9da7cd48af8352327226bba0e955f3c92e2966651365a9" dependencies = [ "base64", "block", From 87fe2b44a19f92fed42263bb398ff6efa25659e9 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 17 Jan 2024 09:36:47 -0300 Subject: [PATCH 42/69] readd schema feature on tauri-config-schema [skip ci] --- core/tauri-config-schema/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/tauri-config-schema/Cargo.toml b/core/tauri-config-schema/Cargo.toml index 7bf09a8e227d..40903b753535 100644 --- a/core/tauri-config-schema/Cargo.toml +++ b/core/tauri-config-schema/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" publish = false [build-dependencies] -tauri-utils = { path = "../tauri-utils" } +tauri-utils = { features = [ "schema" ], path = "../tauri-utils" } schemars = { version = "0.8", features = ["url", "preserve_order"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" From a9f0c9e4e177e59339bc16d42e5e9258cd34a634 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 17 Jan 2024 10:34:49 -0300 Subject: [PATCH 43/69] remove plugin example from workspace, it breaks workspace features resolution [skip ci] --- Cargo.toml | 7 +- .../plugins/tauri-plugin-example/Cargo.lock | 76 ++++++++++++++++--- 2 files changed, 70 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1d1eceff0399..4dd3286e0d4f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,10 +14,8 @@ members = [ # integration tests "core/tests/restart", - - # examples that should be tested by default - "examples/plugins/*" -, "core/tests/acl"] + "core/tests/acl", +] exclude = [ # examples that can be compiled with the tauri CLI @@ -26,6 +24,7 @@ exclude = [ "examples/web/core", "examples/file-associations/src-tauri", "examples/workspace", + "examples/plugins/tauri-plugin-example", ] [workspace.package] diff --git a/examples/plugins/tauri-plugin-example/Cargo.lock b/examples/plugins/tauri-plugin-example/Cargo.lock index c1b6388ec607..78a672832769 100644 --- a/examples/plugins/tauri-plugin-example/Cargo.lock +++ b/examples/plugins/tauri-plugin-example/Cargo.lock @@ -550,6 +550,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +[[package]] +name = "dyn-clone" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" + [[package]] name = "embed-resource" version = "2.4.0" @@ -2107,6 +2113,31 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "schemars" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", + "url", +] + +[[package]] +name = "schemars_derive" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 1.0.109", +] + [[package]] name = "scoped-tls" version = "1.0.1" @@ -2168,6 +2199,17 @@ dependencies = [ "syn 2.0.39", ] +[[package]] +name = "serde_derive_internals" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "serde_json" version = "1.0.108" @@ -2380,6 +2422,12 @@ dependencies = [ "loom", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "string_cache" version = "0.8.7" @@ -2487,7 +2535,7 @@ checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" [[package]] name = "tauri" -version = "2.0.0-alpha.18" +version = "2.0.0-alpha.21" dependencies = [ "anyhow", "bytes", @@ -2506,7 +2554,6 @@ dependencies = [ "mime", "muda", "objc", - "once_cell", "percent-encoding", "raw-window-handle", "reqwest", @@ -2515,6 +2562,7 @@ dependencies = [ "serde_repr", "serialize-to-javascript", "state", + "static_assertions", "swift-rs", "tauri-build", "tauri-macros", @@ -2531,26 +2579,29 @@ dependencies = [ [[package]] name = "tauri-build" -version = "2.0.0-alpha.12" +version = "2.0.0-alpha.14" dependencies = [ "anyhow", "cargo_toml", "dirs-next", + "glob", "heck", "json-patch", "plist", + "schemars", "semver", "serde", "serde_json", "swift-rs", "tauri-utils", "tauri-winres", + "toml 0.8.8", "walkdir", ] [[package]] name = "tauri-codegen" -version = "2.0.0-alpha.11" +version = "2.0.0-alpha.13" dependencies = [ "base64", "ico", @@ -2573,7 +2624,7 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.0.0-alpha.11" +version = "2.0.0-alpha.13" dependencies = [ "heck", "proc-macro2", @@ -2587,13 +2638,17 @@ dependencies = [ name = "tauri-plugin" version = "0.1.0" dependencies = [ - "anyhow", "cargo_metadata", + "glob", + "serde", + "serde_json", "tauri", + "tauri-utils", + "toml 0.8.8", ] [[package]] -name = "tauri-plugin-maybe" +name = "tauri-plugin-example" version = "0.1.0" dependencies = [ "tauri-plugin", @@ -2601,7 +2656,7 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "1.0.0-alpha.5" +version = "1.0.0-alpha.8" dependencies = [ "gtk", "http", @@ -2617,8 +2672,9 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "2.0.0-alpha.11" +version = "2.0.0-alpha.13" dependencies = [ + "cargo_metadata", "ctor", "dunce", "glob", @@ -2632,11 +2688,13 @@ dependencies = [ "phf 0.11.2", "proc-macro2", "quote", + "schemars", "semver", "serde", "serde_json", "serde_with", "thiserror", + "toml 0.8.8", "url", "walkdir", ] From 50651a5e5b09b9ae09b01aa1c347e17466584cb1 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 17 Jan 2024 10:46:48 -0300 Subject: [PATCH 44/69] scope as array, add test [skip ci] --- core/tauri-utils/src/acl/mod.rs | 4 +- core/tauri-utils/src/acl/resolved.rs | 12 ++- .../acl/fixtures/capabilities/scope/cap.toml | 10 ++ .../capabilities/scope/required-plugins.json | 1 + .../acl/fixtures/plugins/fs/deny-home.toml | 6 ++ .../acl/fixtures/plugins/fs/move-tmp.toml | 6 ++ .../fixtures/plugins/fs/read-resources.toml | 8 ++ core/tests/acl/fixtures/plugins/fs/scope.toml | 2 +- .../acl_tests__tests__scope.snap.new | 96 +++++++++++++++++++ .../permissions/global-scope.toml | 2 +- .../permissions/ping-scoped.toml | 2 +- 11 files changed, 140 insertions(+), 9 deletions(-) create mode 100644 core/tests/acl/fixtures/capabilities/scope/cap.toml create mode 100644 core/tests/acl/fixtures/capabilities/scope/required-plugins.json create mode 100644 core/tests/acl/fixtures/plugins/fs/deny-home.toml create mode 100644 core/tests/acl/fixtures/plugins/fs/move-tmp.toml create mode 100644 core/tests/acl/fixtures/plugins/fs/read-resources.toml create mode 100644 core/tests/acl/fixtures/snapshots/acl_tests__tests__scope.snap.new diff --git a/core/tauri-utils/src/acl/mod.rs b/core/tauri-utils/src/acl/mod.rs index cfa4442f7b5f..1ab343afb4bb 100644 --- a/core/tauri-utils/src/acl/mod.rs +++ b/core/tauri-utils/src/acl/mod.rs @@ -138,9 +138,9 @@ pub struct Commands { #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] pub struct Scopes { /// Data that defines what is allowed by the scope. - pub allow: Option, + pub allow: Option>, /// Data that defines what is denied by the scope. - pub deny: Option, + pub deny: Option>, } /// Descriptions of explicit privileges of commands. diff --git a/core/tauri-utils/src/acl/resolved.rs b/core/tauri-utils/src/acl/resolved.rs index bee6e357d9ff..efe431533637 100644 --- a/core/tauri-utils/src/acl/resolved.rs +++ b/core/tauri-utils/src/acl/resolved.rs @@ -5,7 +5,7 @@ //! Resolved ACL for runtime usage. use std::{ - collections::{hash_map::DefaultHasher, BTreeMap}, + collections::{hash_map::DefaultHasher, BTreeMap, HashSet}, hash::{Hash, Hasher}, }; @@ -138,11 +138,13 @@ impl Resolved { .scope .iter() .flat_map(|s| command_scopes.get(s).unwrap().allow.clone()) + .flatten() .collect(), deny: allowed .scope .iter() .flat_map(|s| command_scopes.get(s).unwrap().deny.clone()) + .flatten() .collect(), }; @@ -154,10 +156,12 @@ impl Resolved { allow: global_scope .iter_mut() .flat_map(|s| s.allow.take()) + .flatten() .collect(), deny: global_scope .iter_mut() .flat_map(|s| s.deny.take()) + .flatten() .collect(), }; @@ -168,7 +172,7 @@ impl Resolved { ( key, ResolvedCommand { - windows: cmd.windows, + windows: cmd.windows.into_iter().collect(), scope: cmd.resolved_scope_key, }, ) @@ -180,7 +184,7 @@ impl Resolved { ( key, ResolvedCommand { - windows: cmd.windows, + windows: cmd.windows.into_iter().collect(), scope: cmd.resolved_scope_key, }, ) @@ -196,7 +200,7 @@ impl Resolved { #[derive(Debug, Default)] struct ResolvedCommandTemp { - pub windows: Vec, + pub windows: HashSet, pub scope: Vec, pub resolved_scope_key: Option, } diff --git a/core/tests/acl/fixtures/capabilities/scope/cap.toml b/core/tests/acl/fixtures/capabilities/scope/cap.toml new file mode 100644 index 000000000000..934483076eb2 --- /dev/null +++ b/core/tests/acl/fixtures/capabilities/scope/cap.toml @@ -0,0 +1,10 @@ +identifier = "run-app" +description = "app capability" +windows = ["main"] +permissions = [ + "fs:read", + "fs:allow-app", + "fs:deny-home", + "fs:allow-read-resources", + "fs:allow-move-temp", +] diff --git a/core/tests/acl/fixtures/capabilities/scope/required-plugins.json b/core/tests/acl/fixtures/capabilities/scope/required-plugins.json new file mode 100644 index 000000000000..9ab323181acf --- /dev/null +++ b/core/tests/acl/fixtures/capabilities/scope/required-plugins.json @@ -0,0 +1 @@ +["fs"] diff --git a/core/tests/acl/fixtures/plugins/fs/deny-home.toml b/core/tests/acl/fixtures/plugins/fs/deny-home.toml new file mode 100644 index 000000000000..34b0c9563676 --- /dev/null +++ b/core/tests/acl/fixtures/plugins/fs/deny-home.toml @@ -0,0 +1,6 @@ + +[[permission]] +identifier = "deny-home" +description = "Denies accessing the $HOME path." +[[permission.scope.deny]] +path = "$HOME" diff --git a/core/tests/acl/fixtures/plugins/fs/move-tmp.toml b/core/tests/acl/fixtures/plugins/fs/move-tmp.toml new file mode 100644 index 000000000000..db5854c3a0a6 --- /dev/null +++ b/core/tests/acl/fixtures/plugins/fs/move-tmp.toml @@ -0,0 +1,6 @@ +[[permission]] +identifier = "allow-move-temp" +description = "Enables the move command with the $TEMP base directory." +commands.allow = ["move"] +[[permission.scope.allow]] +path = "$TEMP/*" diff --git a/core/tests/acl/fixtures/plugins/fs/read-resources.toml b/core/tests/acl/fixtures/plugins/fs/read-resources.toml new file mode 100644 index 000000000000..9a8572d7c805 --- /dev/null +++ b/core/tests/acl/fixtures/plugins/fs/read-resources.toml @@ -0,0 +1,8 @@ +[[permission]] +identifier = "allow-read-resources" +description = "Enables the read_file and read_dir command using the $RESOURCE base directory." +commands.allow = ["read_file", "read_dir"] +[[permission.scope.allow]] +path = "$RESOURCE/**" +[[permission.scope.allow]] +path = "$RESOURCE" diff --git a/core/tests/acl/fixtures/plugins/fs/scope.toml b/core/tests/acl/fixtures/plugins/fs/scope.toml index 921b2e91eca6..9c00d0e6cc68 100644 --- a/core/tests/acl/fixtures/plugins/fs/scope.toml +++ b/core/tests/acl/fixtures/plugins/fs/scope.toml @@ -2,5 +2,5 @@ [[permission]] identifier = "allow-app" description = "Allows accessing the $APP path." -[permission.scope.allow] +[[permission.scope.allow]] path = "$APP" diff --git a/core/tests/acl/fixtures/snapshots/acl_tests__tests__scope.snap.new b/core/tests/acl/fixtures/snapshots/acl_tests__tests__scope.snap.new new file mode 100644 index 000000000000..d50e511d15be --- /dev/null +++ b/core/tests/acl/fixtures/snapshots/acl_tests__tests__scope.snap.new @@ -0,0 +1,96 @@ +--- +source: core/tests/acl/src/lib.rs +assertion_line: 49 +expression: resolved +--- +Resolved { + allowed_commands: { + CommandKey { + name: "plugin:fs|move", + context: Local, + }: ResolvedCommand { + windows: [ + "main", + ], + scope: Some( + 18088007599891946824, + ), + }, + CommandKey { + name: "plugin:fs|read_dir", + context: Local, + }: ResolvedCommand { + windows: [ + "main", + ], + scope: Some( + 7912899488978770657, + ), + }, + CommandKey { + name: "plugin:fs|read_file", + context: Local, + }: ResolvedCommand { + windows: [ + "main", + ], + scope: Some( + 7912899488978770657, + ), + }, + }, + denied_commands: {}, + command_scope: { + 7912899488978770657: ResolvedScope { + allow: [ + Map( + { + "path": String( + "$RESOURCE/**", + ), + }, + ), + Map( + { + "path": String( + "$RESOURCE", + ), + }, + ), + ], + deny: [], + }, + 18088007599891946824: ResolvedScope { + allow: [ + Map( + { + "path": String( + "$TEMP/*", + ), + }, + ), + ], + deny: [], + }, + }, + global_scope: ResolvedScope { + allow: [ + Map( + { + "path": String( + "$APP", + ), + }, + ), + ], + deny: [ + Map( + { + "path": String( + "$HOME", + ), + }, + ), + ], + }, +} diff --git a/examples/api/src-tauri/tauri-plugin-sample/permissions/global-scope.toml b/examples/api/src-tauri/tauri-plugin-sample/permissions/global-scope.toml index 4c0940550405..197422645b6d 100644 --- a/examples/api/src-tauri/tauri-plugin-sample/permissions/global-scope.toml +++ b/examples/api/src-tauri/tauri-plugin-sample/permissions/global-scope.toml @@ -3,5 +3,5 @@ [[permission]] identifier = "global-scope" description = "Sets a global scope." -[permission.scope.allow] +[[permission.scope.allow]] path = "global" diff --git a/examples/api/src-tauri/tauri-plugin-sample/permissions/ping-scoped.toml b/examples/api/src-tauri/tauri-plugin-sample/permissions/ping-scoped.toml index 95b321df6c0a..70205ac1e002 100644 --- a/examples/api/src-tauri/tauri-plugin-sample/permissions/ping-scoped.toml +++ b/examples/api/src-tauri/tauri-plugin-sample/permissions/ping-scoped.toml @@ -4,5 +4,5 @@ identifier = "allow-ping-scoped" description = "Enables the ping command with a test scope." commands.allow = ["ping"] -[permission.scope.allow] +[[permission.scope.allow]] path = "x" From 5218e32f5a93cf47c1bd2a47e8365425b5a31119 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 17 Jan 2024 10:57:22 -0300 Subject: [PATCH 45/69] accept new shapshot [skip ci] --- ..._tests__tests__scope.snap.new => acl_tests__tests__scope.snap} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename core/tests/acl/fixtures/snapshots/{acl_tests__tests__scope.snap.new => acl_tests__tests__scope.snap} (100%) diff --git a/core/tests/acl/fixtures/snapshots/acl_tests__tests__scope.snap.new b/core/tests/acl/fixtures/snapshots/acl_tests__tests__scope.snap similarity index 100% rename from core/tests/acl/fixtures/snapshots/acl_tests__tests__scope.snap.new rename to core/tests/acl/fixtures/snapshots/acl_tests__tests__scope.snap From 3edd138ab470f0ebcb2a042db94492c3a40251ea Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 17 Jan 2024 12:45:00 -0300 Subject: [PATCH 46/69] core plugin permissions, default is now a set --- core/tauri-build/src/acl.rs | 2 +- core/tauri-plugin/src/build/mod.rs | 54 +----- core/tauri-utils/src/acl/build.rs | 86 ++++++-- core/tauri-utils/src/acl/plugin.rs | 27 ++- core/tauri-utils/src/acl/resolved.rs | 11 +- core/tauri/Cargo.toml | 1 + core/tauri/build.rs | 183 ++++++++++++++++++ core/tauri/permissions/.gitignore | 1 + .../app/autogenerated/commands/app_hide.toml | 13 ++ .../app/autogenerated/commands/app_show.toml | 13 ++ .../app/autogenerated/commands/name.toml | 13 ++ .../autogenerated/commands/tauri_version.toml | 13 ++ .../app/autogenerated/commands/version.toml | 13 ++ .../app/autogenerated/default.toml | 5 + .../event/autogenerated/commands/emit.toml | 13 ++ .../event/autogenerated/commands/listen.toml | 13 ++ .../autogenerated/commands/unlisten.toml | 13 ++ .../event/autogenerated/default.toml | 5 + .../menu/autogenerated/commands/append.toml | 13 ++ .../commands/create_default.toml | 13 ++ .../menu/autogenerated/commands/get.toml | 13 ++ .../menu/autogenerated/commands/insert.toml | 13 ++ .../autogenerated/commands/is_checked.toml | 13 ++ .../autogenerated/commands/is_enabled.toml | 13 ++ .../menu/autogenerated/commands/items.toml | 13 ++ .../menu/autogenerated/commands/new.toml | 13 ++ .../menu/autogenerated/commands/popup.toml | 13 ++ .../menu/autogenerated/commands/prepend.toml | 13 ++ .../menu/autogenerated/commands/remove.toml | 13 ++ .../autogenerated/commands/remove_at.toml | 13 ++ .../commands/set_accelerator.toml | 13 ++ .../commands/set_as_app_menu.toml | 13 ++ .../commands/set_as_help_menu_for_nsapp.toml | 13 ++ .../commands/set_as_window_menu.toml | 13 ++ .../set_as_windows_menu_for_nsapp.toml | 13 ++ .../autogenerated/commands/set_checked.toml | 13 ++ .../autogenerated/commands/set_enabled.toml | 13 ++ .../menu/autogenerated/commands/set_icon.toml | 13 ++ .../menu/autogenerated/commands/set_text.toml | 13 ++ .../menu/autogenerated/commands/text.toml | 13 ++ .../menu/autogenerated/default.toml | 5 + .../path/autogenerated/commands/basename.toml | 13 ++ .../path/autogenerated/commands/dirname.toml | 13 ++ .../path/autogenerated/commands/extname.toml | 13 ++ .../autogenerated/commands/is_absolute.toml | 13 ++ .../path/autogenerated/commands/join.toml | 13 ++ .../autogenerated/commands/normalize.toml | 13 ++ .../path/autogenerated/commands/resolve.toml | 13 ++ .../commands/resolve_directory.toml | 13 ++ .../path/autogenerated/default.toml | 5 + .../autogenerated/commands/close.toml | 13 ++ .../resources/autogenerated/default.toml | 5 + .../tray/autogenerated/commands/new.toml | 13 ++ .../tray/autogenerated/commands/set_icon.toml | 13 ++ .../commands/set_icon_as_template.toml | 13 ++ .../tray/autogenerated/commands/set_menu.toml | 13 ++ .../commands/set_show_menu_on_left_click.toml | 13 ++ .../commands/set_temp_dir_path.toml | 13 ++ .../autogenerated/commands/set_title.toml | 13 ++ .../autogenerated/commands/set_tooltip.toml | 13 ++ .../autogenerated/commands/set_visible.toml | 13 ++ .../tray/autogenerated/default.toml | 5 + .../commands/available_monitors.toml | 13 ++ .../window/autogenerated/commands/center.toml | 13 ++ .../window/autogenerated/commands/close.toml | 13 ++ .../window/autogenerated/commands/create.toml | 13 ++ .../commands/current_monitor.toml | 13 ++ .../window/autogenerated/commands/hide.toml | 13 ++ .../commands/inner_position.toml | 13 ++ .../autogenerated/commands/inner_size.toml | 13 ++ .../commands/internal_toggle_devtools.toml | 13 ++ .../commands/internal_toggle_maximize.toml | 13 ++ .../autogenerated/commands/is_closable.toml | 13 ++ .../autogenerated/commands/is_decorated.toml | 13 ++ .../autogenerated/commands/is_focused.toml | 13 ++ .../autogenerated/commands/is_fullscreen.toml | 13 ++ .../commands/is_maximizable.toml | 13 ++ .../autogenerated/commands/is_maximized.toml | 13 ++ .../commands/is_minimizable.toml | 13 ++ .../autogenerated/commands/is_minimized.toml | 13 ++ .../autogenerated/commands/is_resizable.toml | 13 ++ .../autogenerated/commands/is_visible.toml | 13 ++ .../autogenerated/commands/maximize.toml | 13 ++ .../autogenerated/commands/minimize.toml | 13 ++ .../commands/outer_position.toml | 13 ++ .../autogenerated/commands/outer_size.toml | 13 ++ .../commands/primary_monitor.toml | 13 ++ .../window/autogenerated/commands/print.toml | 13 ++ .../commands/request_user_attention.toml | 13 ++ .../autogenerated/commands/scale_factor.toml | 13 ++ .../commands/set_always_on_bottom.toml | 13 ++ .../commands/set_always_on_top.toml | 13 ++ .../autogenerated/commands/set_closable.toml | 13 ++ .../commands/set_content_protected.toml | 13 ++ .../commands/set_cursor_grab.toml | 13 ++ .../commands/set_cursor_icon.toml | 13 ++ .../commands/set_cursor_position.toml | 13 ++ .../commands/set_cursor_visible.toml | 13 ++ .../commands/set_decorations.toml | 13 ++ .../autogenerated/commands/set_effects.toml | 13 ++ .../autogenerated/commands/set_focus.toml | 13 ++ .../commands/set_fullscreen.toml | 13 ++ .../autogenerated/commands/set_icon.toml | 13 ++ .../commands/set_ignore_cursor_events.toml | 13 ++ .../autogenerated/commands/set_max_size.toml | 13 ++ .../commands/set_maximizable.toml | 13 ++ .../autogenerated/commands/set_min_size.toml | 13 ++ .../commands/set_minimizable.toml | 13 ++ .../autogenerated/commands/set_position.toml | 13 ++ .../commands/set_progress_bar.toml | 13 ++ .../autogenerated/commands/set_resizable.toml | 13 ++ .../autogenerated/commands/set_shadow.toml | 13 ++ .../autogenerated/commands/set_size.toml | 13 ++ .../commands/set_skip_taskbar.toml | 13 ++ .../autogenerated/commands/set_title.toml | 13 ++ .../window/autogenerated/commands/show.toml | 13 ++ .../commands/start_dragging.toml | 13 ++ .../window/autogenerated/commands/theme.toml | 13 ++ .../window/autogenerated/commands/title.toml | 13 ++ .../commands/toggle_maximize.toml | 13 ++ .../autogenerated/commands/unmaximize.toml | 13 ++ .../autogenerated/commands/unminimize.toml | 13 ++ .../window/autogenerated/default.toml | 5 + core/tauri/src/menu/plugin.rs | 4 +- core/tests/acl/src/lib.rs | 8 +- .../api/src-tauri/capabilities/run-app.toml | 12 +- tooling/api/src/menu/menu.ts | 2 +- 127 files changed, 1740 insertions(+), 90 deletions(-) create mode 100644 core/tauri/permissions/.gitignore create mode 100644 core/tauri/permissions/app/autogenerated/commands/app_hide.toml create mode 100644 core/tauri/permissions/app/autogenerated/commands/app_show.toml create mode 100644 core/tauri/permissions/app/autogenerated/commands/name.toml create mode 100644 core/tauri/permissions/app/autogenerated/commands/tauri_version.toml create mode 100644 core/tauri/permissions/app/autogenerated/commands/version.toml create mode 100644 core/tauri/permissions/app/autogenerated/default.toml create mode 100644 core/tauri/permissions/event/autogenerated/commands/emit.toml create mode 100644 core/tauri/permissions/event/autogenerated/commands/listen.toml create mode 100644 core/tauri/permissions/event/autogenerated/commands/unlisten.toml create mode 100644 core/tauri/permissions/event/autogenerated/default.toml create mode 100644 core/tauri/permissions/menu/autogenerated/commands/append.toml create mode 100644 core/tauri/permissions/menu/autogenerated/commands/create_default.toml create mode 100644 core/tauri/permissions/menu/autogenerated/commands/get.toml create mode 100644 core/tauri/permissions/menu/autogenerated/commands/insert.toml create mode 100644 core/tauri/permissions/menu/autogenerated/commands/is_checked.toml create mode 100644 core/tauri/permissions/menu/autogenerated/commands/is_enabled.toml create mode 100644 core/tauri/permissions/menu/autogenerated/commands/items.toml create mode 100644 core/tauri/permissions/menu/autogenerated/commands/new.toml create mode 100644 core/tauri/permissions/menu/autogenerated/commands/popup.toml create mode 100644 core/tauri/permissions/menu/autogenerated/commands/prepend.toml create mode 100644 core/tauri/permissions/menu/autogenerated/commands/remove.toml create mode 100644 core/tauri/permissions/menu/autogenerated/commands/remove_at.toml create mode 100644 core/tauri/permissions/menu/autogenerated/commands/set_accelerator.toml create mode 100644 core/tauri/permissions/menu/autogenerated/commands/set_as_app_menu.toml create mode 100644 core/tauri/permissions/menu/autogenerated/commands/set_as_help_menu_for_nsapp.toml create mode 100644 core/tauri/permissions/menu/autogenerated/commands/set_as_window_menu.toml create mode 100644 core/tauri/permissions/menu/autogenerated/commands/set_as_windows_menu_for_nsapp.toml create mode 100644 core/tauri/permissions/menu/autogenerated/commands/set_checked.toml create mode 100644 core/tauri/permissions/menu/autogenerated/commands/set_enabled.toml create mode 100644 core/tauri/permissions/menu/autogenerated/commands/set_icon.toml create mode 100644 core/tauri/permissions/menu/autogenerated/commands/set_text.toml create mode 100644 core/tauri/permissions/menu/autogenerated/commands/text.toml create mode 100644 core/tauri/permissions/menu/autogenerated/default.toml create mode 100644 core/tauri/permissions/path/autogenerated/commands/basename.toml create mode 100644 core/tauri/permissions/path/autogenerated/commands/dirname.toml create mode 100644 core/tauri/permissions/path/autogenerated/commands/extname.toml create mode 100644 core/tauri/permissions/path/autogenerated/commands/is_absolute.toml create mode 100644 core/tauri/permissions/path/autogenerated/commands/join.toml create mode 100644 core/tauri/permissions/path/autogenerated/commands/normalize.toml create mode 100644 core/tauri/permissions/path/autogenerated/commands/resolve.toml create mode 100644 core/tauri/permissions/path/autogenerated/commands/resolve_directory.toml create mode 100644 core/tauri/permissions/path/autogenerated/default.toml create mode 100644 core/tauri/permissions/resources/autogenerated/commands/close.toml create mode 100644 core/tauri/permissions/resources/autogenerated/default.toml create mode 100644 core/tauri/permissions/tray/autogenerated/commands/new.toml create mode 100644 core/tauri/permissions/tray/autogenerated/commands/set_icon.toml create mode 100644 core/tauri/permissions/tray/autogenerated/commands/set_icon_as_template.toml create mode 100644 core/tauri/permissions/tray/autogenerated/commands/set_menu.toml create mode 100644 core/tauri/permissions/tray/autogenerated/commands/set_show_menu_on_left_click.toml create mode 100644 core/tauri/permissions/tray/autogenerated/commands/set_temp_dir_path.toml create mode 100644 core/tauri/permissions/tray/autogenerated/commands/set_title.toml create mode 100644 core/tauri/permissions/tray/autogenerated/commands/set_tooltip.toml create mode 100644 core/tauri/permissions/tray/autogenerated/commands/set_visible.toml create mode 100644 core/tauri/permissions/tray/autogenerated/default.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/available_monitors.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/center.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/close.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/create.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/current_monitor.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/hide.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/inner_position.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/inner_size.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/internal_toggle_devtools.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/internal_toggle_maximize.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/is_closable.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/is_decorated.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/is_focused.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/is_fullscreen.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/is_maximizable.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/is_maximized.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/is_minimizable.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/is_minimized.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/is_resizable.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/is_visible.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/maximize.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/minimize.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/outer_position.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/outer_size.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/primary_monitor.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/print.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/request_user_attention.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/scale_factor.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_always_on_bottom.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_always_on_top.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_closable.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_content_protected.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_cursor_grab.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_cursor_icon.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_cursor_position.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_cursor_visible.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_decorations.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_effects.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_focus.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_fullscreen.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_icon.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_ignore_cursor_events.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_max_size.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_maximizable.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_min_size.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_minimizable.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_position.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_progress_bar.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_resizable.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_shadow.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_size.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_skip_taskbar.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/set_title.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/show.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/start_dragging.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/theme.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/title.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/toggle_maximize.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/unmaximize.toml create mode 100644 core/tauri/permissions/window/autogenerated/commands/unminimize.toml create mode 100644 core/tauri/permissions/window/autogenerated/default.toml diff --git a/core/tauri-build/src/acl.rs b/core/tauri-build/src/acl.rs index 1285d405c0f4..f08a5db77ac5 100644 --- a/core/tauri-build/src/acl.rs +++ b/core/tauri-build/src/acl.rs @@ -46,7 +46,7 @@ fn capabilities_schema(plugin_manifests: &BTreeMap) -> RootSch permission_schemas.push(schema_from( plugin, "default", - default.description.as_deref(), + Some(default.description.as_ref()), )); } diff --git a/core/tauri-plugin/src/build/mod.rs b/core/tauri-plugin/src/build/mod.rs index 6283b27df679..b6b8b21dc82c 100644 --- a/core/tauri-plugin/src/build/mod.rs +++ b/core/tauri-plugin/src/build/mod.rs @@ -2,11 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -use std::{ - env::current_dir, - fs::create_dir_all, - path::{Path, PathBuf}, -}; +use std::path::Path; use cargo_metadata::{Metadata, MetadataCommand}; use tauri_utils::acl::{self, Error}; @@ -48,11 +44,14 @@ impl<'a> Builder<'a> { let commands_dir = &autogenerated.join("commands"); if !self.commands.is_empty() { - autogenerate_command_permissions(commands_dir, self.commands); + acl::build::autogenerate_command_permissions(commands_dir, self.commands); } - let permissions = acl::build::define_permissions("./permissions/**/*.*")?; - acl::build::generate_schema(&permissions)?; + let permissions = acl::build::define_permissions( + "./permissions/**/*.*", + &std::env::var("CARGO_PKG_NAME").unwrap(), + )?; + acl::build::generate_schema(&permissions, "./permissions")?; let metadata = find_metadata()?; println!("{metadata:#?}"); @@ -61,45 +60,6 @@ impl<'a> Builder<'a> { } } -fn autogenerate_command_permissions(path: &Path, commands: &[&str]) { - if !path.exists() { - create_dir_all(path).expect("unable to create autogenerated commands dir"); - } - - let cwd = current_dir().unwrap(); - let components_len = path.strip_prefix(&cwd).unwrap_or(path).components().count(); - let schema_path = (1..components_len) - .map(|_| "..") - .collect::() - .join(acl::build::PERMISSION_SCHEMA_FILE_NAME); - - for command in commands { - let slugified_command = command.replace('_', "-"); - let toml = format!( - r###"# Automatically generated - DO NOT EDIT! - -"$schema" = "{schema_path}" - -[[permission]] -identifier = "allow-{slugified_command}" -description = "Enables the {command} command without any pre-configured scope." -commands.allow = ["{command}"] - -[[permission]] -identifier = "deny-{slugified_command}" -description = "Denies the {command} command without any pre-configured scope." -commands.deny = ["{command}"] -"###, - command = command, - slugified_command = slugified_command, - schema_path = schema_path.display() - ); - - std::fs::write(path.join(format!("{command}.toml")), toml) - .unwrap_or_else(|_| panic!("unable to autogenerate ${command}.toml")); - } -} - /// Grab an env var that is expected to be set inside of build scripts. fn build_var(key: &'static str) -> Result { std::env::var(key).map_err(|_| Error::BuildVar(key)) diff --git a/core/tauri-utils/src/acl/build.rs b/core/tauri-utils/src/acl/build.rs index df13049022b9..8360626b6969 100644 --- a/core/tauri-utils/src/acl/build.rs +++ b/core/tauri-utils/src/acl/build.rs @@ -6,10 +6,10 @@ use std::{ collections::{BTreeMap, HashMap}, - env::vars_os, - fs::File, + env::{current_dir, vars_os}, + fs::{create_dir_all, File}, io::{BufWriter, Write}, - path::PathBuf, + path::{Path, PathBuf}, }; use crate::acl::Error; @@ -36,6 +36,8 @@ const CAPABILITY_FILE_EXTENSIONS: &[&str] = &["json", "toml"]; /// Known filename of a capability schema const CAPABILITIES_SCHEMA_FILE_NAME: &str = ".schema.json"; +const CORE_PLUGIN_PERMISSIONS_TOKEN: &str = "__CORE_PLUGIN__"; + /// Capability formats accepted in a capability file. #[derive(Deserialize, schemars::JsonSchema)] #[serde(untagged)] @@ -50,7 +52,7 @@ pub enum CapabilityFile { } /// Write the permissions to a temporary directory and pass it to the immediate consuming crate. -pub fn define_permissions(pattern: &str) -> Result, Error> { +pub fn define_permissions(pattern: &str, pkg_name: &str) -> Result, Error> { let permission_files = glob::glob(pattern)? .flatten() .flat_map(|p| p.canonicalize()) @@ -73,19 +75,24 @@ pub fn define_permissions(pattern: &str) -> Result, Error> { println!("cargo:rerun-if-changed={}", path.display()); } - let permission_files_path = std::env::temp_dir().join(format!( - "{}-permission-files", - std::env::var("CARGO_PKG_NAME").unwrap() - )); + let permission_files_path = std::env::temp_dir().join(format!("{}-permission-files", pkg_name)); std::fs::write( &permission_files_path, serde_json::to_string(&permission_files)?, ) .map_err(Error::WriteFile)?; - println!( - "cargo:{PERMISSION_FILES_PATH_KEY}={}", - permission_files_path.display() - ); + + if let Some(plugin_name) = pkg_name.strip_prefix("tauri:") { + println!( + "cargo:{plugin_name}{CORE_PLUGIN_PERMISSIONS_TOKEN}_{PERMISSION_FILES_PATH_KEY}={}", + permission_files_path.display() + ); + } else { + println!( + "cargo:{PERMISSION_FILES_PATH_KEY}={}", + permission_files_path.display() + ); + } parse_permissions(permission_files) } @@ -204,12 +211,16 @@ fn permissions_schema(permissions: &[PermissionFile]) -> RootSchema { } /// Generate and write a schema based on the format of a [`PermissionFile`]. -pub fn generate_schema(permissions: &[PermissionFile]) -> Result<(), Error> { +pub fn generate_schema>( + permissions: &[PermissionFile], + out_dir: P, +) -> Result<(), Error> { let schema = permissions_schema(permissions); let schema_str = serde_json::to_string_pretty(&schema).unwrap(); - let out_path = PathBuf::from("permissions").join(PERMISSION_SCHEMA_FILE_NAME); - let mut schema_file = BufWriter::new(File::create(out_path).map_err(Error::CreateFile)?); + let mut schema_file = BufWriter::new( + File::create(out_dir.as_ref().join(PERMISSION_SCHEMA_FILE_NAME)).map_err(Error::CreateFile)?, + ); write!(schema_file, "{schema_str}").map_err(Error::WriteFile)?; Ok(()) } @@ -224,6 +235,11 @@ pub fn read_permissions() -> Result>, Error> if let Some(plugin_crate_name_var) = key .strip_prefix("DEP_") .and_then(|v| v.strip_suffix(&format!("_{PERMISSION_FILES_PATH_KEY}"))) + .map(|v| { + v.strip_suffix(CORE_PLUGIN_PERMISSIONS_TOKEN) + .and_then(|v| v.strip_prefix("TAURI_")) + .unwrap_or(v) + }) { let permissions_path = PathBuf::from(value); let permissions_str = std::fs::read_to_string(&permissions_path).map_err(Error::ReadFile)?; @@ -258,3 +274,43 @@ fn parse_permissions(paths: Vec) -> Result, Error> } Ok(permissions) } + +/// Autogenerate permission files for a list of commands. +pub fn autogenerate_command_permissions(path: &Path, commands: &[&str]) { + if !path.exists() { + create_dir_all(path).expect("unable to create autogenerated commands dir"); + } + + let cwd = current_dir().unwrap(); + let components_len = path.strip_prefix(&cwd).unwrap_or(path).components().count(); + let schema_path = (1..components_len) + .map(|_| "..") + .collect::() + .join(PERMISSION_SCHEMA_FILE_NAME); + + for command in commands { + let slugified_command = command.replace('_', "-"); + let toml = format!( + r###"# Automatically generated - DO NOT EDIT! + +"$schema" = "{schema_path}" + +[[permission]] +identifier = "allow-{slugified_command}" +description = "Enables the {command} command without any pre-configured scope." +commands.allow = ["{command}"] + +[[permission]] +identifier = "deny-{slugified_command}" +description = "Denies the {command} command without any pre-configured scope." +commands.deny = ["{command}"] +"###, + command = command, + slugified_command = slugified_command, + schema_path = schema_path.display() + ); + + std::fs::write(path.join(format!("{command}.toml")), toml) + .unwrap_or_else(|_| panic!("unable to autogenerate ${command}.toml")); + } +} diff --git a/core/tauri-utils/src/acl/plugin.rs b/core/tauri-utils/src/acl/plugin.rs index 816406a23808..d825a631cad0 100644 --- a/core/tauri-utils/src/acl/plugin.rs +++ b/core/tauri-utils/src/acl/plugin.rs @@ -6,10 +6,10 @@ use std::{collections::HashMap, num::NonZeroU64}; -use super::{Commands, Permission, PermissionSet, Scopes}; +use super::{Permission, PermissionSet}; use serde::{Deserialize, Serialize}; -/// The default permission of the plugin. +/// The default permission set of the plugin. /// /// Works similarly to a permission with the "default" identifier. #[derive(Debug, Deserialize)] @@ -21,13 +21,8 @@ pub struct DefaultPermission { /// Human-readable description of what the permission does. pub description: Option, - /// Allowed or denied commands when using this permission. - #[serde(default)] - pub commands: Commands, - - /// Allowed or denied scoped when using this permission. - #[serde(default)] - pub scope: Scopes, + /// All permissions this set contains. + pub permissions: Vec, } /// Permission file that can define a default permission, a set of permissions or a list of inlined permissions. @@ -50,10 +45,10 @@ pub struct PermissionFile { } /// Plugin manifest. -#[derive(Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize)] pub struct Manifest { /// Default permission. - pub default_permission: Option, + pub default_permission: Option, /// Plugin permissions. pub permissions: HashMap, /// Plugin permission sets. @@ -71,12 +66,12 @@ impl Manifest { for permission_file in permission_files { if let Some(default) = permission_file.default { - manifest.default_permission.replace(Permission { + manifest.default_permission.replace(PermissionSet { identifier: "default".into(), - version: default.version, - description: default.description, - commands: default.commands, - scope: default.scope, + description: default + .description + .unwrap_or_else(|| "Default plugin permissions.".to_string()), + permissions: default.permissions, }); } diff --git a/core/tauri-utils/src/acl/resolved.rs b/core/tauri-utils/src/acl/resolved.rs index efe431533637..37dacb4d5f44 100644 --- a/core/tauri-utils/src/acl/resolved.rs +++ b/core/tauri-utils/src/acl/resolved.rs @@ -272,11 +272,14 @@ fn get_permissions<'a>( })?; if permission_name == "default" { - Ok(vec![manifest.default_permission.as_ref().ok_or_else( - || Error::MissingDefaultPermission { + manifest + .default_permission + .as_ref() + .ok_or_else(|| Error::UnknownPermission { plugin: plugin_name.to_string(), - }, - )?]) + permission: permission_name.to_string(), + }) + .and_then(|default| get_permission_set_permissions(manifest, default)) } else if let Some(set) = manifest.permission_sets.get(permission_name) { get_permission_set_permissions(manifest, set) } else if let Some(permission) = manifest.permissions.get(permission_name) { diff --git a/core/tauri/Cargo.toml b/core/tauri/Cargo.toml index d64633c1b812..27f054e8663f 100644 --- a/core/tauri/Cargo.toml +++ b/core/tauri/Cargo.toml @@ -111,6 +111,7 @@ swift-rs = "1.0.6" [build-dependencies] heck = "0.4" tauri-build = { path = "../tauri-build/", version = "2.0.0-alpha.14" } +tauri-utils = { path = "../tauri-utils/", version = "2.0.0-alpha.13", features = [ "build" ] } [dev-dependencies] proptest = "1.4.0" diff --git a/core/tauri/build.rs b/core/tauri/build.rs index 01a589c86409..3136aabc3eb1 100644 --- a/core/tauri/build.rs +++ b/core/tauri/build.rs @@ -15,6 +15,146 @@ use std::{ }; static CHECKED_FEATURES: OnceLock>> = OnceLock::new(); +const PLUGINS: &[(&str, &[(&str, bool)])] = &[ + // (plugin_name, &[(command, enabled-by_default)]) + ( + "path", + &[ + ("resolve_directory", true), + ("resolve", true), + ("normalize", true), + ("join", true), + ("dirname", true), + ("extname", true), + ("basename", true), + ("is_absolute", true), + ], + ), + ( + "event", + &[("listen", true), ("unlisten", true), ("emit", true)], + ), + ( + "window", + &[ + ("create", false), + // getters + ("scale_factor", true), + ("inner_position", true), + ("outer_position", true), + ("inner_size", true), + ("outer_size", true), + ("is_fullscreen", true), + ("is_minimized", true), + ("is_maximized", true), + ("is_focused", true), + ("is_decorated", true), + ("is_resizable", true), + ("is_maximizable", true), + ("is_minimizable", true), + ("is_closable", true), + ("is_visible", true), + ("title", true), + ("current_monitor", true), + ("primary_monitor", true), + ("available_monitors", true), + ("theme", true), + // setters + ("center", false), + ("request_user_attention", false), + ("set_resizable", false), + ("set_maximizable", false), + ("set_minimizable", false), + ("set_closable", false), + ("set_title", false), + ("maximize", false), + ("unmaximize", false), + ("minimize", false), + ("unminimize", false), + ("show", false), + ("hide", false), + ("close", false), + ("set_decorations", false), + ("set_shadow", false), + ("set_effects", false), + ("set_always_on_top", false), + ("set_always_on_bottom", false), + ("set_content_protected", false), + ("set_size", false), + ("set_min_size", false), + ("set_max_size", false), + ("set_position", false), + ("set_fullscreen", false), + ("set_focus", false), + ("set_skip_taskbar", false), + ("set_cursor_grab", false), + ("set_cursor_visible", false), + ("set_cursor_icon", false), + ("set_cursor_position", false), + ("set_ignore_cursor_events", false), + ("start_dragging", false), + ("set_progress_bar", false), + ("print", false), + ("set_icon", false), + ("toggle_maximize", false), + // internal + ("internal_toggle_maximize", true), + ("internal_toggle_devtools", true), + ], + ), + ( + "app", + &[ + ("version", true), + ("name", true), + ("tauri_version", true), + ("app_show", false), + ("app_hide", false), + ], + ), + ("resources", &[("close", true)]), + ( + "menu", + &[ + ("new", false), + ("append", false), + ("prepend", false), + ("insert", false), + ("remove", false), + ("remove_at", false), + ("items", false), + ("get", false), + ("popup", false), + ("create_default", false), + ("set_as_app_menu", false), + ("set_as_window_menu", false), + ("text", false), + ("set_text", false), + ("is_enabled", false), + ("set_enabled", false), + ("set_accelerator", false), + ("set_as_windows_menu_for_nsapp", false), + ("set_as_help_menu_for_nsapp", false), + ("is_checked", false), + ("set_checked", false), + ("set_icon", false), + ], + ), + ( + "tray", + &[ + ("new", false), + ("set_icon", false), + ("set_menu", false), + ("set_tooltip", false), + ("set_title", false), + ("set_visible", false), + ("set_temp_dir_path", false), + ("set_icon_as_template", false), + ("set_show_menu_on_left_click", false), + ], + ), +]; // checks if the given Cargo feature is enabled. fn has_feature(feature: &str) -> bool { @@ -134,6 +274,49 @@ fn main() { println!("cargo:ios_library_path={}", lib_path.display()); } } + + define_permissions(); +} + +fn define_permissions() { + for (plugin, commands) in PLUGINS { + let autogenerated = PathBuf::from(format!("permissions/{plugin}/autogenerated/")); + let commands_dir = autogenerated.join("commands"); + + tauri_utils::acl::build::autogenerate_command_permissions( + &commands_dir, + &commands.iter().map(|(cmd, _)| *cmd).collect::>(), + ); + let default_permissions = commands + .iter() + .filter(|(_cmd, default)| *default) + .map(|(cmd, _)| { + let slugified_command = cmd.replace('_', "-"); + format!("\"allow-{}\"", slugified_command) + }) + .collect::>() + .join(", "); + + let default_toml = format!( + r###"# Automatically generated - DO NOT EDIT! + +[default] +description = "Default permissions for the plugin." +permissions = [{default_permissions}] +"###, + ); + + std::fs::write(autogenerated.join("default.toml"), default_toml) + .unwrap_or_else(|_| panic!("unable to autogenerate default permissions")); + + let permissions = tauri_utils::acl::build::define_permissions( + &format!("./permissions/{plugin}/**/*.toml"), + &format!("tauri:{plugin}"), + ) + .unwrap_or_else(|e| panic!("failed to define permissions for {plugin}: {e}")); + tauri_utils::acl::build::generate_schema(&permissions, format!("./permissions/{plugin}")) + .unwrap_or_else(|e| panic!("failed to generate schema for {plugin}: {e}")); + } } fn add_manifest() { diff --git a/core/tauri/permissions/.gitignore b/core/tauri/permissions/.gitignore new file mode 100644 index 000000000000..9fe3b17f12ec --- /dev/null +++ b/core/tauri/permissions/.gitignore @@ -0,0 +1 @@ +.schema.json diff --git a/core/tauri/permissions/app/autogenerated/commands/app_hide.toml b/core/tauri/permissions/app/autogenerated/commands/app_hide.toml new file mode 100644 index 000000000000..e29f148d8fe4 --- /dev/null +++ b/core/tauri/permissions/app/autogenerated/commands/app_hide.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-app-hide" +description = "Enables the app_hide command without any pre-configured scope." +commands.allow = ["app_hide"] + +[[permission]] +identifier = "deny-app-hide" +description = "Denies the app_hide command without any pre-configured scope." +commands.deny = ["app_hide"] diff --git a/core/tauri/permissions/app/autogenerated/commands/app_show.toml b/core/tauri/permissions/app/autogenerated/commands/app_show.toml new file mode 100644 index 000000000000..ec77dc52d3b5 --- /dev/null +++ b/core/tauri/permissions/app/autogenerated/commands/app_show.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-app-show" +description = "Enables the app_show command without any pre-configured scope." +commands.allow = ["app_show"] + +[[permission]] +identifier = "deny-app-show" +description = "Denies the app_show command without any pre-configured scope." +commands.deny = ["app_show"] diff --git a/core/tauri/permissions/app/autogenerated/commands/name.toml b/core/tauri/permissions/app/autogenerated/commands/name.toml new file mode 100644 index 000000000000..b5cc148938ca --- /dev/null +++ b/core/tauri/permissions/app/autogenerated/commands/name.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-name" +description = "Enables the name command without any pre-configured scope." +commands.allow = ["name"] + +[[permission]] +identifier = "deny-name" +description = "Denies the name command without any pre-configured scope." +commands.deny = ["name"] diff --git a/core/tauri/permissions/app/autogenerated/commands/tauri_version.toml b/core/tauri/permissions/app/autogenerated/commands/tauri_version.toml new file mode 100644 index 000000000000..5c4a41efd03f --- /dev/null +++ b/core/tauri/permissions/app/autogenerated/commands/tauri_version.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-tauri-version" +description = "Enables the tauri_version command without any pre-configured scope." +commands.allow = ["tauri_version"] + +[[permission]] +identifier = "deny-tauri-version" +description = "Denies the tauri_version command without any pre-configured scope." +commands.deny = ["tauri_version"] diff --git a/core/tauri/permissions/app/autogenerated/commands/version.toml b/core/tauri/permissions/app/autogenerated/commands/version.toml new file mode 100644 index 000000000000..c33b4a4a1ada --- /dev/null +++ b/core/tauri/permissions/app/autogenerated/commands/version.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-version" +description = "Enables the version command without any pre-configured scope." +commands.allow = ["version"] + +[[permission]] +identifier = "deny-version" +description = "Denies the version command without any pre-configured scope." +commands.deny = ["version"] diff --git a/core/tauri/permissions/app/autogenerated/default.toml b/core/tauri/permissions/app/autogenerated/default.toml new file mode 100644 index 000000000000..0896c91a68be --- /dev/null +++ b/core/tauri/permissions/app/autogenerated/default.toml @@ -0,0 +1,5 @@ +# Automatically generated - DO NOT EDIT! + +[default] +description = "Default permissions for the plugin." +permissions = ["allow-version", "allow-name", "allow-tauri-version"] diff --git a/core/tauri/permissions/event/autogenerated/commands/emit.toml b/core/tauri/permissions/event/autogenerated/commands/emit.toml new file mode 100644 index 000000000000..db6ef6e09d33 --- /dev/null +++ b/core/tauri/permissions/event/autogenerated/commands/emit.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-emit" +description = "Enables the emit command without any pre-configured scope." +commands.allow = ["emit"] + +[[permission]] +identifier = "deny-emit" +description = "Denies the emit command without any pre-configured scope." +commands.deny = ["emit"] diff --git a/core/tauri/permissions/event/autogenerated/commands/listen.toml b/core/tauri/permissions/event/autogenerated/commands/listen.toml new file mode 100644 index 000000000000..f32005b07179 --- /dev/null +++ b/core/tauri/permissions/event/autogenerated/commands/listen.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-listen" +description = "Enables the listen command without any pre-configured scope." +commands.allow = ["listen"] + +[[permission]] +identifier = "deny-listen" +description = "Denies the listen command without any pre-configured scope." +commands.deny = ["listen"] diff --git a/core/tauri/permissions/event/autogenerated/commands/unlisten.toml b/core/tauri/permissions/event/autogenerated/commands/unlisten.toml new file mode 100644 index 000000000000..2a01c4cafc93 --- /dev/null +++ b/core/tauri/permissions/event/autogenerated/commands/unlisten.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-unlisten" +description = "Enables the unlisten command without any pre-configured scope." +commands.allow = ["unlisten"] + +[[permission]] +identifier = "deny-unlisten" +description = "Denies the unlisten command without any pre-configured scope." +commands.deny = ["unlisten"] diff --git a/core/tauri/permissions/event/autogenerated/default.toml b/core/tauri/permissions/event/autogenerated/default.toml new file mode 100644 index 000000000000..8c627d632d52 --- /dev/null +++ b/core/tauri/permissions/event/autogenerated/default.toml @@ -0,0 +1,5 @@ +# Automatically generated - DO NOT EDIT! + +[default] +description = "Default permissions for the plugin." +permissions = ["allow-listen", "allow-unlisten", "allow-emit"] diff --git a/core/tauri/permissions/menu/autogenerated/commands/append.toml b/core/tauri/permissions/menu/autogenerated/commands/append.toml new file mode 100644 index 000000000000..4af693b62322 --- /dev/null +++ b/core/tauri/permissions/menu/autogenerated/commands/append.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-append" +description = "Enables the append command without any pre-configured scope." +commands.allow = ["append"] + +[[permission]] +identifier = "deny-append" +description = "Denies the append command without any pre-configured scope." +commands.deny = ["append"] diff --git a/core/tauri/permissions/menu/autogenerated/commands/create_default.toml b/core/tauri/permissions/menu/autogenerated/commands/create_default.toml new file mode 100644 index 000000000000..0c88974a52a5 --- /dev/null +++ b/core/tauri/permissions/menu/autogenerated/commands/create_default.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-create-default" +description = "Enables the create_default command without any pre-configured scope." +commands.allow = ["create_default"] + +[[permission]] +identifier = "deny-create-default" +description = "Denies the create_default command without any pre-configured scope." +commands.deny = ["create_default"] diff --git a/core/tauri/permissions/menu/autogenerated/commands/get.toml b/core/tauri/permissions/menu/autogenerated/commands/get.toml new file mode 100644 index 000000000000..4aeb868b8641 --- /dev/null +++ b/core/tauri/permissions/menu/autogenerated/commands/get.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-get" +description = "Enables the get command without any pre-configured scope." +commands.allow = ["get"] + +[[permission]] +identifier = "deny-get" +description = "Denies the get command without any pre-configured scope." +commands.deny = ["get"] diff --git a/core/tauri/permissions/menu/autogenerated/commands/insert.toml b/core/tauri/permissions/menu/autogenerated/commands/insert.toml new file mode 100644 index 000000000000..e204edbc7f55 --- /dev/null +++ b/core/tauri/permissions/menu/autogenerated/commands/insert.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-insert" +description = "Enables the insert command without any pre-configured scope." +commands.allow = ["insert"] + +[[permission]] +identifier = "deny-insert" +description = "Denies the insert command without any pre-configured scope." +commands.deny = ["insert"] diff --git a/core/tauri/permissions/menu/autogenerated/commands/is_checked.toml b/core/tauri/permissions/menu/autogenerated/commands/is_checked.toml new file mode 100644 index 000000000000..ea05872dd94d --- /dev/null +++ b/core/tauri/permissions/menu/autogenerated/commands/is_checked.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-is-checked" +description = "Enables the is_checked command without any pre-configured scope." +commands.allow = ["is_checked"] + +[[permission]] +identifier = "deny-is-checked" +description = "Denies the is_checked command without any pre-configured scope." +commands.deny = ["is_checked"] diff --git a/core/tauri/permissions/menu/autogenerated/commands/is_enabled.toml b/core/tauri/permissions/menu/autogenerated/commands/is_enabled.toml new file mode 100644 index 000000000000..10741b37c6c1 --- /dev/null +++ b/core/tauri/permissions/menu/autogenerated/commands/is_enabled.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-is-enabled" +description = "Enables the is_enabled command without any pre-configured scope." +commands.allow = ["is_enabled"] + +[[permission]] +identifier = "deny-is-enabled" +description = "Denies the is_enabled command without any pre-configured scope." +commands.deny = ["is_enabled"] diff --git a/core/tauri/permissions/menu/autogenerated/commands/items.toml b/core/tauri/permissions/menu/autogenerated/commands/items.toml new file mode 100644 index 000000000000..c87f128d507b --- /dev/null +++ b/core/tauri/permissions/menu/autogenerated/commands/items.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-items" +description = "Enables the items command without any pre-configured scope." +commands.allow = ["items"] + +[[permission]] +identifier = "deny-items" +description = "Denies the items command without any pre-configured scope." +commands.deny = ["items"] diff --git a/core/tauri/permissions/menu/autogenerated/commands/new.toml b/core/tauri/permissions/menu/autogenerated/commands/new.toml new file mode 100644 index 000000000000..a8db386c0558 --- /dev/null +++ b/core/tauri/permissions/menu/autogenerated/commands/new.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-new" +description = "Enables the new command without any pre-configured scope." +commands.allow = ["new"] + +[[permission]] +identifier = "deny-new" +description = "Denies the new command without any pre-configured scope." +commands.deny = ["new"] diff --git a/core/tauri/permissions/menu/autogenerated/commands/popup.toml b/core/tauri/permissions/menu/autogenerated/commands/popup.toml new file mode 100644 index 000000000000..df17be75f524 --- /dev/null +++ b/core/tauri/permissions/menu/autogenerated/commands/popup.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-popup" +description = "Enables the popup command without any pre-configured scope." +commands.allow = ["popup"] + +[[permission]] +identifier = "deny-popup" +description = "Denies the popup command without any pre-configured scope." +commands.deny = ["popup"] diff --git a/core/tauri/permissions/menu/autogenerated/commands/prepend.toml b/core/tauri/permissions/menu/autogenerated/commands/prepend.toml new file mode 100644 index 000000000000..e7df4dbdabea --- /dev/null +++ b/core/tauri/permissions/menu/autogenerated/commands/prepend.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-prepend" +description = "Enables the prepend command without any pre-configured scope." +commands.allow = ["prepend"] + +[[permission]] +identifier = "deny-prepend" +description = "Denies the prepend command without any pre-configured scope." +commands.deny = ["prepend"] diff --git a/core/tauri/permissions/menu/autogenerated/commands/remove.toml b/core/tauri/permissions/menu/autogenerated/commands/remove.toml new file mode 100644 index 000000000000..99f3eb665683 --- /dev/null +++ b/core/tauri/permissions/menu/autogenerated/commands/remove.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-remove" +description = "Enables the remove command without any pre-configured scope." +commands.allow = ["remove"] + +[[permission]] +identifier = "deny-remove" +description = "Denies the remove command without any pre-configured scope." +commands.deny = ["remove"] diff --git a/core/tauri/permissions/menu/autogenerated/commands/remove_at.toml b/core/tauri/permissions/menu/autogenerated/commands/remove_at.toml new file mode 100644 index 000000000000..4acea0d6364d --- /dev/null +++ b/core/tauri/permissions/menu/autogenerated/commands/remove_at.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-remove-at" +description = "Enables the remove_at command without any pre-configured scope." +commands.allow = ["remove_at"] + +[[permission]] +identifier = "deny-remove-at" +description = "Denies the remove_at command without any pre-configured scope." +commands.deny = ["remove_at"] diff --git a/core/tauri/permissions/menu/autogenerated/commands/set_accelerator.toml b/core/tauri/permissions/menu/autogenerated/commands/set_accelerator.toml new file mode 100644 index 000000000000..02cb03f662b1 --- /dev/null +++ b/core/tauri/permissions/menu/autogenerated/commands/set_accelerator.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-accelerator" +description = "Enables the set_accelerator command without any pre-configured scope." +commands.allow = ["set_accelerator"] + +[[permission]] +identifier = "deny-set-accelerator" +description = "Denies the set_accelerator command without any pre-configured scope." +commands.deny = ["set_accelerator"] diff --git a/core/tauri/permissions/menu/autogenerated/commands/set_as_app_menu.toml b/core/tauri/permissions/menu/autogenerated/commands/set_as_app_menu.toml new file mode 100644 index 000000000000..6a0ac4639816 --- /dev/null +++ b/core/tauri/permissions/menu/autogenerated/commands/set_as_app_menu.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-as-app-menu" +description = "Enables the set_as_app_menu command without any pre-configured scope." +commands.allow = ["set_as_app_menu"] + +[[permission]] +identifier = "deny-set-as-app-menu" +description = "Denies the set_as_app_menu command without any pre-configured scope." +commands.deny = ["set_as_app_menu"] diff --git a/core/tauri/permissions/menu/autogenerated/commands/set_as_help_menu_for_nsapp.toml b/core/tauri/permissions/menu/autogenerated/commands/set_as_help_menu_for_nsapp.toml new file mode 100644 index 000000000000..36b0ecd244b4 --- /dev/null +++ b/core/tauri/permissions/menu/autogenerated/commands/set_as_help_menu_for_nsapp.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-as-help-menu-for-nsapp" +description = "Enables the set_as_help_menu_for_nsapp command without any pre-configured scope." +commands.allow = ["set_as_help_menu_for_nsapp"] + +[[permission]] +identifier = "deny-set-as-help-menu-for-nsapp" +description = "Denies the set_as_help_menu_for_nsapp command without any pre-configured scope." +commands.deny = ["set_as_help_menu_for_nsapp"] diff --git a/core/tauri/permissions/menu/autogenerated/commands/set_as_window_menu.toml b/core/tauri/permissions/menu/autogenerated/commands/set_as_window_menu.toml new file mode 100644 index 000000000000..714c1e472672 --- /dev/null +++ b/core/tauri/permissions/menu/autogenerated/commands/set_as_window_menu.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-as-window-menu" +description = "Enables the set_as_window_menu command without any pre-configured scope." +commands.allow = ["set_as_window_menu"] + +[[permission]] +identifier = "deny-set-as-window-menu" +description = "Denies the set_as_window_menu command without any pre-configured scope." +commands.deny = ["set_as_window_menu"] diff --git a/core/tauri/permissions/menu/autogenerated/commands/set_as_windows_menu_for_nsapp.toml b/core/tauri/permissions/menu/autogenerated/commands/set_as_windows_menu_for_nsapp.toml new file mode 100644 index 000000000000..9614aaa2c5a0 --- /dev/null +++ b/core/tauri/permissions/menu/autogenerated/commands/set_as_windows_menu_for_nsapp.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-as-windows-menu-for-nsapp" +description = "Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope." +commands.allow = ["set_as_windows_menu_for_nsapp"] + +[[permission]] +identifier = "deny-set-as-windows-menu-for-nsapp" +description = "Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope." +commands.deny = ["set_as_windows_menu_for_nsapp"] diff --git a/core/tauri/permissions/menu/autogenerated/commands/set_checked.toml b/core/tauri/permissions/menu/autogenerated/commands/set_checked.toml new file mode 100644 index 000000000000..4be3e4453c32 --- /dev/null +++ b/core/tauri/permissions/menu/autogenerated/commands/set_checked.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-checked" +description = "Enables the set_checked command without any pre-configured scope." +commands.allow = ["set_checked"] + +[[permission]] +identifier = "deny-set-checked" +description = "Denies the set_checked command without any pre-configured scope." +commands.deny = ["set_checked"] diff --git a/core/tauri/permissions/menu/autogenerated/commands/set_enabled.toml b/core/tauri/permissions/menu/autogenerated/commands/set_enabled.toml new file mode 100644 index 000000000000..0b085e3af5ff --- /dev/null +++ b/core/tauri/permissions/menu/autogenerated/commands/set_enabled.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-enabled" +description = "Enables the set_enabled command without any pre-configured scope." +commands.allow = ["set_enabled"] + +[[permission]] +identifier = "deny-set-enabled" +description = "Denies the set_enabled command without any pre-configured scope." +commands.deny = ["set_enabled"] diff --git a/core/tauri/permissions/menu/autogenerated/commands/set_icon.toml b/core/tauri/permissions/menu/autogenerated/commands/set_icon.toml new file mode 100644 index 000000000000..408288069419 --- /dev/null +++ b/core/tauri/permissions/menu/autogenerated/commands/set_icon.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-icon" +description = "Enables the set_icon command without any pre-configured scope." +commands.allow = ["set_icon"] + +[[permission]] +identifier = "deny-set-icon" +description = "Denies the set_icon command without any pre-configured scope." +commands.deny = ["set_icon"] diff --git a/core/tauri/permissions/menu/autogenerated/commands/set_text.toml b/core/tauri/permissions/menu/autogenerated/commands/set_text.toml new file mode 100644 index 000000000000..793ae2243209 --- /dev/null +++ b/core/tauri/permissions/menu/autogenerated/commands/set_text.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-text" +description = "Enables the set_text command without any pre-configured scope." +commands.allow = ["set_text"] + +[[permission]] +identifier = "deny-set-text" +description = "Denies the set_text command without any pre-configured scope." +commands.deny = ["set_text"] diff --git a/core/tauri/permissions/menu/autogenerated/commands/text.toml b/core/tauri/permissions/menu/autogenerated/commands/text.toml new file mode 100644 index 000000000000..108f8dbcd416 --- /dev/null +++ b/core/tauri/permissions/menu/autogenerated/commands/text.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-text" +description = "Enables the text command without any pre-configured scope." +commands.allow = ["text"] + +[[permission]] +identifier = "deny-text" +description = "Denies the text command without any pre-configured scope." +commands.deny = ["text"] diff --git a/core/tauri/permissions/menu/autogenerated/default.toml b/core/tauri/permissions/menu/autogenerated/default.toml new file mode 100644 index 000000000000..6887d8a2bb3c --- /dev/null +++ b/core/tauri/permissions/menu/autogenerated/default.toml @@ -0,0 +1,5 @@ +# Automatically generated - DO NOT EDIT! + +[default] +description = "Default permissions for the plugin." +permissions = [] diff --git a/core/tauri/permissions/path/autogenerated/commands/basename.toml b/core/tauri/permissions/path/autogenerated/commands/basename.toml new file mode 100644 index 000000000000..280466f0710a --- /dev/null +++ b/core/tauri/permissions/path/autogenerated/commands/basename.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-basename" +description = "Enables the basename command without any pre-configured scope." +commands.allow = ["basename"] + +[[permission]] +identifier = "deny-basename" +description = "Denies the basename command without any pre-configured scope." +commands.deny = ["basename"] diff --git a/core/tauri/permissions/path/autogenerated/commands/dirname.toml b/core/tauri/permissions/path/autogenerated/commands/dirname.toml new file mode 100644 index 000000000000..ef7d234eaa58 --- /dev/null +++ b/core/tauri/permissions/path/autogenerated/commands/dirname.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-dirname" +description = "Enables the dirname command without any pre-configured scope." +commands.allow = ["dirname"] + +[[permission]] +identifier = "deny-dirname" +description = "Denies the dirname command without any pre-configured scope." +commands.deny = ["dirname"] diff --git a/core/tauri/permissions/path/autogenerated/commands/extname.toml b/core/tauri/permissions/path/autogenerated/commands/extname.toml new file mode 100644 index 000000000000..92771bb4ac6b --- /dev/null +++ b/core/tauri/permissions/path/autogenerated/commands/extname.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-extname" +description = "Enables the extname command without any pre-configured scope." +commands.allow = ["extname"] + +[[permission]] +identifier = "deny-extname" +description = "Denies the extname command without any pre-configured scope." +commands.deny = ["extname"] diff --git a/core/tauri/permissions/path/autogenerated/commands/is_absolute.toml b/core/tauri/permissions/path/autogenerated/commands/is_absolute.toml new file mode 100644 index 000000000000..dbd6d564bc2c --- /dev/null +++ b/core/tauri/permissions/path/autogenerated/commands/is_absolute.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-is-absolute" +description = "Enables the is_absolute command without any pre-configured scope." +commands.allow = ["is_absolute"] + +[[permission]] +identifier = "deny-is-absolute" +description = "Denies the is_absolute command without any pre-configured scope." +commands.deny = ["is_absolute"] diff --git a/core/tauri/permissions/path/autogenerated/commands/join.toml b/core/tauri/permissions/path/autogenerated/commands/join.toml new file mode 100644 index 000000000000..cf402e3e85cc --- /dev/null +++ b/core/tauri/permissions/path/autogenerated/commands/join.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-join" +description = "Enables the join command without any pre-configured scope." +commands.allow = ["join"] + +[[permission]] +identifier = "deny-join" +description = "Denies the join command without any pre-configured scope." +commands.deny = ["join"] diff --git a/core/tauri/permissions/path/autogenerated/commands/normalize.toml b/core/tauri/permissions/path/autogenerated/commands/normalize.toml new file mode 100644 index 000000000000..4a1f4fe295e6 --- /dev/null +++ b/core/tauri/permissions/path/autogenerated/commands/normalize.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-normalize" +description = "Enables the normalize command without any pre-configured scope." +commands.allow = ["normalize"] + +[[permission]] +identifier = "deny-normalize" +description = "Denies the normalize command without any pre-configured scope." +commands.deny = ["normalize"] diff --git a/core/tauri/permissions/path/autogenerated/commands/resolve.toml b/core/tauri/permissions/path/autogenerated/commands/resolve.toml new file mode 100644 index 000000000000..bcae8ee6a10c --- /dev/null +++ b/core/tauri/permissions/path/autogenerated/commands/resolve.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-resolve" +description = "Enables the resolve command without any pre-configured scope." +commands.allow = ["resolve"] + +[[permission]] +identifier = "deny-resolve" +description = "Denies the resolve command without any pre-configured scope." +commands.deny = ["resolve"] diff --git a/core/tauri/permissions/path/autogenerated/commands/resolve_directory.toml b/core/tauri/permissions/path/autogenerated/commands/resolve_directory.toml new file mode 100644 index 000000000000..2bbd9186d0ce --- /dev/null +++ b/core/tauri/permissions/path/autogenerated/commands/resolve_directory.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-resolve-directory" +description = "Enables the resolve_directory command without any pre-configured scope." +commands.allow = ["resolve_directory"] + +[[permission]] +identifier = "deny-resolve-directory" +description = "Denies the resolve_directory command without any pre-configured scope." +commands.deny = ["resolve_directory"] diff --git a/core/tauri/permissions/path/autogenerated/default.toml b/core/tauri/permissions/path/autogenerated/default.toml new file mode 100644 index 000000000000..1d1748599a6c --- /dev/null +++ b/core/tauri/permissions/path/autogenerated/default.toml @@ -0,0 +1,5 @@ +# Automatically generated - DO NOT EDIT! + +[default] +description = "Default permissions for the plugin." +permissions = ["allow-resolve-directory", "allow-resolve", "allow-normalize", "allow-join", "allow-dirname", "allow-extname", "allow-basename", "allow-is-absolute"] diff --git a/core/tauri/permissions/resources/autogenerated/commands/close.toml b/core/tauri/permissions/resources/autogenerated/commands/close.toml new file mode 100644 index 000000000000..1df7316c8d97 --- /dev/null +++ b/core/tauri/permissions/resources/autogenerated/commands/close.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-close" +description = "Enables the close command without any pre-configured scope." +commands.allow = ["close"] + +[[permission]] +identifier = "deny-close" +description = "Denies the close command without any pre-configured scope." +commands.deny = ["close"] diff --git a/core/tauri/permissions/resources/autogenerated/default.toml b/core/tauri/permissions/resources/autogenerated/default.toml new file mode 100644 index 000000000000..baf14d674d79 --- /dev/null +++ b/core/tauri/permissions/resources/autogenerated/default.toml @@ -0,0 +1,5 @@ +# Automatically generated - DO NOT EDIT! + +[default] +description = "Default permissions for the plugin." +permissions = ["allow-close"] diff --git a/core/tauri/permissions/tray/autogenerated/commands/new.toml b/core/tauri/permissions/tray/autogenerated/commands/new.toml new file mode 100644 index 000000000000..a8db386c0558 --- /dev/null +++ b/core/tauri/permissions/tray/autogenerated/commands/new.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-new" +description = "Enables the new command without any pre-configured scope." +commands.allow = ["new"] + +[[permission]] +identifier = "deny-new" +description = "Denies the new command without any pre-configured scope." +commands.deny = ["new"] diff --git a/core/tauri/permissions/tray/autogenerated/commands/set_icon.toml b/core/tauri/permissions/tray/autogenerated/commands/set_icon.toml new file mode 100644 index 000000000000..408288069419 --- /dev/null +++ b/core/tauri/permissions/tray/autogenerated/commands/set_icon.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-icon" +description = "Enables the set_icon command without any pre-configured scope." +commands.allow = ["set_icon"] + +[[permission]] +identifier = "deny-set-icon" +description = "Denies the set_icon command without any pre-configured scope." +commands.deny = ["set_icon"] diff --git a/core/tauri/permissions/tray/autogenerated/commands/set_icon_as_template.toml b/core/tauri/permissions/tray/autogenerated/commands/set_icon_as_template.toml new file mode 100644 index 000000000000..329e1f72ba0e --- /dev/null +++ b/core/tauri/permissions/tray/autogenerated/commands/set_icon_as_template.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-icon-as-template" +description = "Enables the set_icon_as_template command without any pre-configured scope." +commands.allow = ["set_icon_as_template"] + +[[permission]] +identifier = "deny-set-icon-as-template" +description = "Denies the set_icon_as_template command without any pre-configured scope." +commands.deny = ["set_icon_as_template"] diff --git a/core/tauri/permissions/tray/autogenerated/commands/set_menu.toml b/core/tauri/permissions/tray/autogenerated/commands/set_menu.toml new file mode 100644 index 000000000000..1a58a064fbb9 --- /dev/null +++ b/core/tauri/permissions/tray/autogenerated/commands/set_menu.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-menu" +description = "Enables the set_menu command without any pre-configured scope." +commands.allow = ["set_menu"] + +[[permission]] +identifier = "deny-set-menu" +description = "Denies the set_menu command without any pre-configured scope." +commands.deny = ["set_menu"] diff --git a/core/tauri/permissions/tray/autogenerated/commands/set_show_menu_on_left_click.toml b/core/tauri/permissions/tray/autogenerated/commands/set_show_menu_on_left_click.toml new file mode 100644 index 000000000000..e5fd9774beca --- /dev/null +++ b/core/tauri/permissions/tray/autogenerated/commands/set_show_menu_on_left_click.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-show-menu-on-left-click" +description = "Enables the set_show_menu_on_left_click command without any pre-configured scope." +commands.allow = ["set_show_menu_on_left_click"] + +[[permission]] +identifier = "deny-set-show-menu-on-left-click" +description = "Denies the set_show_menu_on_left_click command without any pre-configured scope." +commands.deny = ["set_show_menu_on_left_click"] diff --git a/core/tauri/permissions/tray/autogenerated/commands/set_temp_dir_path.toml b/core/tauri/permissions/tray/autogenerated/commands/set_temp_dir_path.toml new file mode 100644 index 000000000000..4c3510af9bed --- /dev/null +++ b/core/tauri/permissions/tray/autogenerated/commands/set_temp_dir_path.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-temp-dir-path" +description = "Enables the set_temp_dir_path command without any pre-configured scope." +commands.allow = ["set_temp_dir_path"] + +[[permission]] +identifier = "deny-set-temp-dir-path" +description = "Denies the set_temp_dir_path command without any pre-configured scope." +commands.deny = ["set_temp_dir_path"] diff --git a/core/tauri/permissions/tray/autogenerated/commands/set_title.toml b/core/tauri/permissions/tray/autogenerated/commands/set_title.toml new file mode 100644 index 000000000000..872f35577bbe --- /dev/null +++ b/core/tauri/permissions/tray/autogenerated/commands/set_title.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-title" +description = "Enables the set_title command without any pre-configured scope." +commands.allow = ["set_title"] + +[[permission]] +identifier = "deny-set-title" +description = "Denies the set_title command without any pre-configured scope." +commands.deny = ["set_title"] diff --git a/core/tauri/permissions/tray/autogenerated/commands/set_tooltip.toml b/core/tauri/permissions/tray/autogenerated/commands/set_tooltip.toml new file mode 100644 index 000000000000..5a80dd195404 --- /dev/null +++ b/core/tauri/permissions/tray/autogenerated/commands/set_tooltip.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-tooltip" +description = "Enables the set_tooltip command without any pre-configured scope." +commands.allow = ["set_tooltip"] + +[[permission]] +identifier = "deny-set-tooltip" +description = "Denies the set_tooltip command without any pre-configured scope." +commands.deny = ["set_tooltip"] diff --git a/core/tauri/permissions/tray/autogenerated/commands/set_visible.toml b/core/tauri/permissions/tray/autogenerated/commands/set_visible.toml new file mode 100644 index 000000000000..f88d57ed30fc --- /dev/null +++ b/core/tauri/permissions/tray/autogenerated/commands/set_visible.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-visible" +description = "Enables the set_visible command without any pre-configured scope." +commands.allow = ["set_visible"] + +[[permission]] +identifier = "deny-set-visible" +description = "Denies the set_visible command without any pre-configured scope." +commands.deny = ["set_visible"] diff --git a/core/tauri/permissions/tray/autogenerated/default.toml b/core/tauri/permissions/tray/autogenerated/default.toml new file mode 100644 index 000000000000..6887d8a2bb3c --- /dev/null +++ b/core/tauri/permissions/tray/autogenerated/default.toml @@ -0,0 +1,5 @@ +# Automatically generated - DO NOT EDIT! + +[default] +description = "Default permissions for the plugin." +permissions = [] diff --git a/core/tauri/permissions/window/autogenerated/commands/available_monitors.toml b/core/tauri/permissions/window/autogenerated/commands/available_monitors.toml new file mode 100644 index 000000000000..34ec3287aacd --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/available_monitors.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-available-monitors" +description = "Enables the available_monitors command without any pre-configured scope." +commands.allow = ["available_monitors"] + +[[permission]] +identifier = "deny-available-monitors" +description = "Denies the available_monitors command without any pre-configured scope." +commands.deny = ["available_monitors"] diff --git a/core/tauri/permissions/window/autogenerated/commands/center.toml b/core/tauri/permissions/window/autogenerated/commands/center.toml new file mode 100644 index 000000000000..75d71f775291 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/center.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-center" +description = "Enables the center command without any pre-configured scope." +commands.allow = ["center"] + +[[permission]] +identifier = "deny-center" +description = "Denies the center command without any pre-configured scope." +commands.deny = ["center"] diff --git a/core/tauri/permissions/window/autogenerated/commands/close.toml b/core/tauri/permissions/window/autogenerated/commands/close.toml new file mode 100644 index 000000000000..1df7316c8d97 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/close.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-close" +description = "Enables the close command without any pre-configured scope." +commands.allow = ["close"] + +[[permission]] +identifier = "deny-close" +description = "Denies the close command without any pre-configured scope." +commands.deny = ["close"] diff --git a/core/tauri/permissions/window/autogenerated/commands/create.toml b/core/tauri/permissions/window/autogenerated/commands/create.toml new file mode 100644 index 000000000000..af9db7b368a7 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/create.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-create" +description = "Enables the create command without any pre-configured scope." +commands.allow = ["create"] + +[[permission]] +identifier = "deny-create" +description = "Denies the create command without any pre-configured scope." +commands.deny = ["create"] diff --git a/core/tauri/permissions/window/autogenerated/commands/current_monitor.toml b/core/tauri/permissions/window/autogenerated/commands/current_monitor.toml new file mode 100644 index 000000000000..79d0870c8e1b --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/current_monitor.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-current-monitor" +description = "Enables the current_monitor command without any pre-configured scope." +commands.allow = ["current_monitor"] + +[[permission]] +identifier = "deny-current-monitor" +description = "Denies the current_monitor command without any pre-configured scope." +commands.deny = ["current_monitor"] diff --git a/core/tauri/permissions/window/autogenerated/commands/hide.toml b/core/tauri/permissions/window/autogenerated/commands/hide.toml new file mode 100644 index 000000000000..331c3b18b645 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/hide.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-hide" +description = "Enables the hide command without any pre-configured scope." +commands.allow = ["hide"] + +[[permission]] +identifier = "deny-hide" +description = "Denies the hide command without any pre-configured scope." +commands.deny = ["hide"] diff --git a/core/tauri/permissions/window/autogenerated/commands/inner_position.toml b/core/tauri/permissions/window/autogenerated/commands/inner_position.toml new file mode 100644 index 000000000000..67e6872fe3c0 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/inner_position.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-inner-position" +description = "Enables the inner_position command without any pre-configured scope." +commands.allow = ["inner_position"] + +[[permission]] +identifier = "deny-inner-position" +description = "Denies the inner_position command without any pre-configured scope." +commands.deny = ["inner_position"] diff --git a/core/tauri/permissions/window/autogenerated/commands/inner_size.toml b/core/tauri/permissions/window/autogenerated/commands/inner_size.toml new file mode 100644 index 000000000000..8f7ae0f22fc6 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/inner_size.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-inner-size" +description = "Enables the inner_size command without any pre-configured scope." +commands.allow = ["inner_size"] + +[[permission]] +identifier = "deny-inner-size" +description = "Denies the inner_size command without any pre-configured scope." +commands.deny = ["inner_size"] diff --git a/core/tauri/permissions/window/autogenerated/commands/internal_toggle_devtools.toml b/core/tauri/permissions/window/autogenerated/commands/internal_toggle_devtools.toml new file mode 100644 index 000000000000..a8474bd2ac82 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/internal_toggle_devtools.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-internal-toggle-devtools" +description = "Enables the internal_toggle_devtools command without any pre-configured scope." +commands.allow = ["internal_toggle_devtools"] + +[[permission]] +identifier = "deny-internal-toggle-devtools" +description = "Denies the internal_toggle_devtools command without any pre-configured scope." +commands.deny = ["internal_toggle_devtools"] diff --git a/core/tauri/permissions/window/autogenerated/commands/internal_toggle_maximize.toml b/core/tauri/permissions/window/autogenerated/commands/internal_toggle_maximize.toml new file mode 100644 index 000000000000..fd1dd4c54294 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/internal_toggle_maximize.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-internal-toggle-maximize" +description = "Enables the internal_toggle_maximize command without any pre-configured scope." +commands.allow = ["internal_toggle_maximize"] + +[[permission]] +identifier = "deny-internal-toggle-maximize" +description = "Denies the internal_toggle_maximize command without any pre-configured scope." +commands.deny = ["internal_toggle_maximize"] diff --git a/core/tauri/permissions/window/autogenerated/commands/is_closable.toml b/core/tauri/permissions/window/autogenerated/commands/is_closable.toml new file mode 100644 index 000000000000..6d0a9e921a64 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/is_closable.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-is-closable" +description = "Enables the is_closable command without any pre-configured scope." +commands.allow = ["is_closable"] + +[[permission]] +identifier = "deny-is-closable" +description = "Denies the is_closable command without any pre-configured scope." +commands.deny = ["is_closable"] diff --git a/core/tauri/permissions/window/autogenerated/commands/is_decorated.toml b/core/tauri/permissions/window/autogenerated/commands/is_decorated.toml new file mode 100644 index 000000000000..50f284ed45a8 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/is_decorated.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-is-decorated" +description = "Enables the is_decorated command without any pre-configured scope." +commands.allow = ["is_decorated"] + +[[permission]] +identifier = "deny-is-decorated" +description = "Denies the is_decorated command without any pre-configured scope." +commands.deny = ["is_decorated"] diff --git a/core/tauri/permissions/window/autogenerated/commands/is_focused.toml b/core/tauri/permissions/window/autogenerated/commands/is_focused.toml new file mode 100644 index 000000000000..e8b9b6f92abd --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/is_focused.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-is-focused" +description = "Enables the is_focused command without any pre-configured scope." +commands.allow = ["is_focused"] + +[[permission]] +identifier = "deny-is-focused" +description = "Denies the is_focused command without any pre-configured scope." +commands.deny = ["is_focused"] diff --git a/core/tauri/permissions/window/autogenerated/commands/is_fullscreen.toml b/core/tauri/permissions/window/autogenerated/commands/is_fullscreen.toml new file mode 100644 index 000000000000..c870464626f3 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/is_fullscreen.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-is-fullscreen" +description = "Enables the is_fullscreen command without any pre-configured scope." +commands.allow = ["is_fullscreen"] + +[[permission]] +identifier = "deny-is-fullscreen" +description = "Denies the is_fullscreen command without any pre-configured scope." +commands.deny = ["is_fullscreen"] diff --git a/core/tauri/permissions/window/autogenerated/commands/is_maximizable.toml b/core/tauri/permissions/window/autogenerated/commands/is_maximizable.toml new file mode 100644 index 000000000000..0e1888e5c137 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/is_maximizable.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-is-maximizable" +description = "Enables the is_maximizable command without any pre-configured scope." +commands.allow = ["is_maximizable"] + +[[permission]] +identifier = "deny-is-maximizable" +description = "Denies the is_maximizable command without any pre-configured scope." +commands.deny = ["is_maximizable"] diff --git a/core/tauri/permissions/window/autogenerated/commands/is_maximized.toml b/core/tauri/permissions/window/autogenerated/commands/is_maximized.toml new file mode 100644 index 000000000000..655d3e3c313d --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/is_maximized.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-is-maximized" +description = "Enables the is_maximized command without any pre-configured scope." +commands.allow = ["is_maximized"] + +[[permission]] +identifier = "deny-is-maximized" +description = "Denies the is_maximized command without any pre-configured scope." +commands.deny = ["is_maximized"] diff --git a/core/tauri/permissions/window/autogenerated/commands/is_minimizable.toml b/core/tauri/permissions/window/autogenerated/commands/is_minimizable.toml new file mode 100644 index 000000000000..fb3b85c1dbd7 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/is_minimizable.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-is-minimizable" +description = "Enables the is_minimizable command without any pre-configured scope." +commands.allow = ["is_minimizable"] + +[[permission]] +identifier = "deny-is-minimizable" +description = "Denies the is_minimizable command without any pre-configured scope." +commands.deny = ["is_minimizable"] diff --git a/core/tauri/permissions/window/autogenerated/commands/is_minimized.toml b/core/tauri/permissions/window/autogenerated/commands/is_minimized.toml new file mode 100644 index 000000000000..88dc3c189a63 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/is_minimized.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-is-minimized" +description = "Enables the is_minimized command without any pre-configured scope." +commands.allow = ["is_minimized"] + +[[permission]] +identifier = "deny-is-minimized" +description = "Denies the is_minimized command without any pre-configured scope." +commands.deny = ["is_minimized"] diff --git a/core/tauri/permissions/window/autogenerated/commands/is_resizable.toml b/core/tauri/permissions/window/autogenerated/commands/is_resizable.toml new file mode 100644 index 000000000000..760982c3b9b5 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/is_resizable.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-is-resizable" +description = "Enables the is_resizable command without any pre-configured scope." +commands.allow = ["is_resizable"] + +[[permission]] +identifier = "deny-is-resizable" +description = "Denies the is_resizable command without any pre-configured scope." +commands.deny = ["is_resizable"] diff --git a/core/tauri/permissions/window/autogenerated/commands/is_visible.toml b/core/tauri/permissions/window/autogenerated/commands/is_visible.toml new file mode 100644 index 000000000000..3bce7072c829 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/is_visible.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-is-visible" +description = "Enables the is_visible command without any pre-configured scope." +commands.allow = ["is_visible"] + +[[permission]] +identifier = "deny-is-visible" +description = "Denies the is_visible command without any pre-configured scope." +commands.deny = ["is_visible"] diff --git a/core/tauri/permissions/window/autogenerated/commands/maximize.toml b/core/tauri/permissions/window/autogenerated/commands/maximize.toml new file mode 100644 index 000000000000..0e4d3be5b60b --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/maximize.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-maximize" +description = "Enables the maximize command without any pre-configured scope." +commands.allow = ["maximize"] + +[[permission]] +identifier = "deny-maximize" +description = "Denies the maximize command without any pre-configured scope." +commands.deny = ["maximize"] diff --git a/core/tauri/permissions/window/autogenerated/commands/minimize.toml b/core/tauri/permissions/window/autogenerated/commands/minimize.toml new file mode 100644 index 000000000000..fedb5b0086f9 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/minimize.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-minimize" +description = "Enables the minimize command without any pre-configured scope." +commands.allow = ["minimize"] + +[[permission]] +identifier = "deny-minimize" +description = "Denies the minimize command without any pre-configured scope." +commands.deny = ["minimize"] diff --git a/core/tauri/permissions/window/autogenerated/commands/outer_position.toml b/core/tauri/permissions/window/autogenerated/commands/outer_position.toml new file mode 100644 index 000000000000..308d239b5e7a --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/outer_position.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-outer-position" +description = "Enables the outer_position command without any pre-configured scope." +commands.allow = ["outer_position"] + +[[permission]] +identifier = "deny-outer-position" +description = "Denies the outer_position command without any pre-configured scope." +commands.deny = ["outer_position"] diff --git a/core/tauri/permissions/window/autogenerated/commands/outer_size.toml b/core/tauri/permissions/window/autogenerated/commands/outer_size.toml new file mode 100644 index 000000000000..6e1b931255f2 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/outer_size.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-outer-size" +description = "Enables the outer_size command without any pre-configured scope." +commands.allow = ["outer_size"] + +[[permission]] +identifier = "deny-outer-size" +description = "Denies the outer_size command without any pre-configured scope." +commands.deny = ["outer_size"] diff --git a/core/tauri/permissions/window/autogenerated/commands/primary_monitor.toml b/core/tauri/permissions/window/autogenerated/commands/primary_monitor.toml new file mode 100644 index 000000000000..32baaac916c6 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/primary_monitor.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-primary-monitor" +description = "Enables the primary_monitor command without any pre-configured scope." +commands.allow = ["primary_monitor"] + +[[permission]] +identifier = "deny-primary-monitor" +description = "Denies the primary_monitor command without any pre-configured scope." +commands.deny = ["primary_monitor"] diff --git a/core/tauri/permissions/window/autogenerated/commands/print.toml b/core/tauri/permissions/window/autogenerated/commands/print.toml new file mode 100644 index 000000000000..289a28f75fe5 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/print.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-print" +description = "Enables the print command without any pre-configured scope." +commands.allow = ["print"] + +[[permission]] +identifier = "deny-print" +description = "Denies the print command without any pre-configured scope." +commands.deny = ["print"] diff --git a/core/tauri/permissions/window/autogenerated/commands/request_user_attention.toml b/core/tauri/permissions/window/autogenerated/commands/request_user_attention.toml new file mode 100644 index 000000000000..44bffe87f885 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/request_user_attention.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-request-user-attention" +description = "Enables the request_user_attention command without any pre-configured scope." +commands.allow = ["request_user_attention"] + +[[permission]] +identifier = "deny-request-user-attention" +description = "Denies the request_user_attention command without any pre-configured scope." +commands.deny = ["request_user_attention"] diff --git a/core/tauri/permissions/window/autogenerated/commands/scale_factor.toml b/core/tauri/permissions/window/autogenerated/commands/scale_factor.toml new file mode 100644 index 000000000000..73079e5e892d --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/scale_factor.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-scale-factor" +description = "Enables the scale_factor command without any pre-configured scope." +commands.allow = ["scale_factor"] + +[[permission]] +identifier = "deny-scale-factor" +description = "Denies the scale_factor command without any pre-configured scope." +commands.deny = ["scale_factor"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_always_on_bottom.toml b/core/tauri/permissions/window/autogenerated/commands/set_always_on_bottom.toml new file mode 100644 index 000000000000..f51731f0509d --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_always_on_bottom.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-always-on-bottom" +description = "Enables the set_always_on_bottom command without any pre-configured scope." +commands.allow = ["set_always_on_bottom"] + +[[permission]] +identifier = "deny-set-always-on-bottom" +description = "Denies the set_always_on_bottom command without any pre-configured scope." +commands.deny = ["set_always_on_bottom"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_always_on_top.toml b/core/tauri/permissions/window/autogenerated/commands/set_always_on_top.toml new file mode 100644 index 000000000000..645742a989b4 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_always_on_top.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-always-on-top" +description = "Enables the set_always_on_top command without any pre-configured scope." +commands.allow = ["set_always_on_top"] + +[[permission]] +identifier = "deny-set-always-on-top" +description = "Denies the set_always_on_top command without any pre-configured scope." +commands.deny = ["set_always_on_top"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_closable.toml b/core/tauri/permissions/window/autogenerated/commands/set_closable.toml new file mode 100644 index 000000000000..8f67794836c0 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_closable.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-closable" +description = "Enables the set_closable command without any pre-configured scope." +commands.allow = ["set_closable"] + +[[permission]] +identifier = "deny-set-closable" +description = "Denies the set_closable command without any pre-configured scope." +commands.deny = ["set_closable"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_content_protected.toml b/core/tauri/permissions/window/autogenerated/commands/set_content_protected.toml new file mode 100644 index 000000000000..9948afdb8844 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_content_protected.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-content-protected" +description = "Enables the set_content_protected command without any pre-configured scope." +commands.allow = ["set_content_protected"] + +[[permission]] +identifier = "deny-set-content-protected" +description = "Denies the set_content_protected command without any pre-configured scope." +commands.deny = ["set_content_protected"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_cursor_grab.toml b/core/tauri/permissions/window/autogenerated/commands/set_cursor_grab.toml new file mode 100644 index 000000000000..962b37a41eee --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_cursor_grab.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-cursor-grab" +description = "Enables the set_cursor_grab command without any pre-configured scope." +commands.allow = ["set_cursor_grab"] + +[[permission]] +identifier = "deny-set-cursor-grab" +description = "Denies the set_cursor_grab command without any pre-configured scope." +commands.deny = ["set_cursor_grab"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_cursor_icon.toml b/core/tauri/permissions/window/autogenerated/commands/set_cursor_icon.toml new file mode 100644 index 000000000000..89eae85ba25f --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_cursor_icon.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-cursor-icon" +description = "Enables the set_cursor_icon command without any pre-configured scope." +commands.allow = ["set_cursor_icon"] + +[[permission]] +identifier = "deny-set-cursor-icon" +description = "Denies the set_cursor_icon command without any pre-configured scope." +commands.deny = ["set_cursor_icon"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_cursor_position.toml b/core/tauri/permissions/window/autogenerated/commands/set_cursor_position.toml new file mode 100644 index 000000000000..ad752b80d1bf --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_cursor_position.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-cursor-position" +description = "Enables the set_cursor_position command without any pre-configured scope." +commands.allow = ["set_cursor_position"] + +[[permission]] +identifier = "deny-set-cursor-position" +description = "Denies the set_cursor_position command without any pre-configured scope." +commands.deny = ["set_cursor_position"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_cursor_visible.toml b/core/tauri/permissions/window/autogenerated/commands/set_cursor_visible.toml new file mode 100644 index 000000000000..69ed51cd84e0 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_cursor_visible.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-cursor-visible" +description = "Enables the set_cursor_visible command without any pre-configured scope." +commands.allow = ["set_cursor_visible"] + +[[permission]] +identifier = "deny-set-cursor-visible" +description = "Denies the set_cursor_visible command without any pre-configured scope." +commands.deny = ["set_cursor_visible"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_decorations.toml b/core/tauri/permissions/window/autogenerated/commands/set_decorations.toml new file mode 100644 index 000000000000..590a0c5dd12d --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_decorations.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-decorations" +description = "Enables the set_decorations command without any pre-configured scope." +commands.allow = ["set_decorations"] + +[[permission]] +identifier = "deny-set-decorations" +description = "Denies the set_decorations command without any pre-configured scope." +commands.deny = ["set_decorations"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_effects.toml b/core/tauri/permissions/window/autogenerated/commands/set_effects.toml new file mode 100644 index 000000000000..b957124875d7 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_effects.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-effects" +description = "Enables the set_effects command without any pre-configured scope." +commands.allow = ["set_effects"] + +[[permission]] +identifier = "deny-set-effects" +description = "Denies the set_effects command without any pre-configured scope." +commands.deny = ["set_effects"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_focus.toml b/core/tauri/permissions/window/autogenerated/commands/set_focus.toml new file mode 100644 index 000000000000..ce4cbd12f3d9 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_focus.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-focus" +description = "Enables the set_focus command without any pre-configured scope." +commands.allow = ["set_focus"] + +[[permission]] +identifier = "deny-set-focus" +description = "Denies the set_focus command without any pre-configured scope." +commands.deny = ["set_focus"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_fullscreen.toml b/core/tauri/permissions/window/autogenerated/commands/set_fullscreen.toml new file mode 100644 index 000000000000..34483410a552 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_fullscreen.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-fullscreen" +description = "Enables the set_fullscreen command without any pre-configured scope." +commands.allow = ["set_fullscreen"] + +[[permission]] +identifier = "deny-set-fullscreen" +description = "Denies the set_fullscreen command without any pre-configured scope." +commands.deny = ["set_fullscreen"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_icon.toml b/core/tauri/permissions/window/autogenerated/commands/set_icon.toml new file mode 100644 index 000000000000..408288069419 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_icon.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-icon" +description = "Enables the set_icon command without any pre-configured scope." +commands.allow = ["set_icon"] + +[[permission]] +identifier = "deny-set-icon" +description = "Denies the set_icon command without any pre-configured scope." +commands.deny = ["set_icon"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_ignore_cursor_events.toml b/core/tauri/permissions/window/autogenerated/commands/set_ignore_cursor_events.toml new file mode 100644 index 000000000000..55563130929f --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_ignore_cursor_events.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-ignore-cursor-events" +description = "Enables the set_ignore_cursor_events command without any pre-configured scope." +commands.allow = ["set_ignore_cursor_events"] + +[[permission]] +identifier = "deny-set-ignore-cursor-events" +description = "Denies the set_ignore_cursor_events command without any pre-configured scope." +commands.deny = ["set_ignore_cursor_events"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_max_size.toml b/core/tauri/permissions/window/autogenerated/commands/set_max_size.toml new file mode 100644 index 000000000000..573e7bdead88 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_max_size.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-max-size" +description = "Enables the set_max_size command without any pre-configured scope." +commands.allow = ["set_max_size"] + +[[permission]] +identifier = "deny-set-max-size" +description = "Denies the set_max_size command without any pre-configured scope." +commands.deny = ["set_max_size"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_maximizable.toml b/core/tauri/permissions/window/autogenerated/commands/set_maximizable.toml new file mode 100644 index 000000000000..45c6e1f764eb --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_maximizable.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-maximizable" +description = "Enables the set_maximizable command without any pre-configured scope." +commands.allow = ["set_maximizable"] + +[[permission]] +identifier = "deny-set-maximizable" +description = "Denies the set_maximizable command without any pre-configured scope." +commands.deny = ["set_maximizable"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_min_size.toml b/core/tauri/permissions/window/autogenerated/commands/set_min_size.toml new file mode 100644 index 000000000000..0a4d961890df --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_min_size.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-min-size" +description = "Enables the set_min_size command without any pre-configured scope." +commands.allow = ["set_min_size"] + +[[permission]] +identifier = "deny-set-min-size" +description = "Denies the set_min_size command without any pre-configured scope." +commands.deny = ["set_min_size"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_minimizable.toml b/core/tauri/permissions/window/autogenerated/commands/set_minimizable.toml new file mode 100644 index 000000000000..5e331b43baa9 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_minimizable.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-minimizable" +description = "Enables the set_minimizable command without any pre-configured scope." +commands.allow = ["set_minimizable"] + +[[permission]] +identifier = "deny-set-minimizable" +description = "Denies the set_minimizable command without any pre-configured scope." +commands.deny = ["set_minimizable"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_position.toml b/core/tauri/permissions/window/autogenerated/commands/set_position.toml new file mode 100644 index 000000000000..068a577aa9b8 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_position.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-position" +description = "Enables the set_position command without any pre-configured scope." +commands.allow = ["set_position"] + +[[permission]] +identifier = "deny-set-position" +description = "Denies the set_position command without any pre-configured scope." +commands.deny = ["set_position"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_progress_bar.toml b/core/tauri/permissions/window/autogenerated/commands/set_progress_bar.toml new file mode 100644 index 000000000000..0b9f68a197ca --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_progress_bar.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-progress-bar" +description = "Enables the set_progress_bar command without any pre-configured scope." +commands.allow = ["set_progress_bar"] + +[[permission]] +identifier = "deny-set-progress-bar" +description = "Denies the set_progress_bar command without any pre-configured scope." +commands.deny = ["set_progress_bar"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_resizable.toml b/core/tauri/permissions/window/autogenerated/commands/set_resizable.toml new file mode 100644 index 000000000000..50367b95f39e --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_resizable.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-resizable" +description = "Enables the set_resizable command without any pre-configured scope." +commands.allow = ["set_resizable"] + +[[permission]] +identifier = "deny-set-resizable" +description = "Denies the set_resizable command without any pre-configured scope." +commands.deny = ["set_resizable"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_shadow.toml b/core/tauri/permissions/window/autogenerated/commands/set_shadow.toml new file mode 100644 index 000000000000..f6a8536ebdfe --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_shadow.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-shadow" +description = "Enables the set_shadow command without any pre-configured scope." +commands.allow = ["set_shadow"] + +[[permission]] +identifier = "deny-set-shadow" +description = "Denies the set_shadow command without any pre-configured scope." +commands.deny = ["set_shadow"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_size.toml b/core/tauri/permissions/window/autogenerated/commands/set_size.toml new file mode 100644 index 000000000000..4f1b86ce9c57 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_size.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-size" +description = "Enables the set_size command without any pre-configured scope." +commands.allow = ["set_size"] + +[[permission]] +identifier = "deny-set-size" +description = "Denies the set_size command without any pre-configured scope." +commands.deny = ["set_size"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_skip_taskbar.toml b/core/tauri/permissions/window/autogenerated/commands/set_skip_taskbar.toml new file mode 100644 index 000000000000..2a90116c48d2 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_skip_taskbar.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-skip-taskbar" +description = "Enables the set_skip_taskbar command without any pre-configured scope." +commands.allow = ["set_skip_taskbar"] + +[[permission]] +identifier = "deny-set-skip-taskbar" +description = "Denies the set_skip_taskbar command without any pre-configured scope." +commands.deny = ["set_skip_taskbar"] diff --git a/core/tauri/permissions/window/autogenerated/commands/set_title.toml b/core/tauri/permissions/window/autogenerated/commands/set_title.toml new file mode 100644 index 000000000000..872f35577bbe --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/set_title.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-set-title" +description = "Enables the set_title command without any pre-configured scope." +commands.allow = ["set_title"] + +[[permission]] +identifier = "deny-set-title" +description = "Denies the set_title command without any pre-configured scope." +commands.deny = ["set_title"] diff --git a/core/tauri/permissions/window/autogenerated/commands/show.toml b/core/tauri/permissions/window/autogenerated/commands/show.toml new file mode 100644 index 000000000000..5ba13eb9bec7 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/show.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-show" +description = "Enables the show command without any pre-configured scope." +commands.allow = ["show"] + +[[permission]] +identifier = "deny-show" +description = "Denies the show command without any pre-configured scope." +commands.deny = ["show"] diff --git a/core/tauri/permissions/window/autogenerated/commands/start_dragging.toml b/core/tauri/permissions/window/autogenerated/commands/start_dragging.toml new file mode 100644 index 000000000000..61e4e9cb789c --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/start_dragging.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-start-dragging" +description = "Enables the start_dragging command without any pre-configured scope." +commands.allow = ["start_dragging"] + +[[permission]] +identifier = "deny-start-dragging" +description = "Denies the start_dragging command without any pre-configured scope." +commands.deny = ["start_dragging"] diff --git a/core/tauri/permissions/window/autogenerated/commands/theme.toml b/core/tauri/permissions/window/autogenerated/commands/theme.toml new file mode 100644 index 000000000000..4b7b4fd01733 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/theme.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-theme" +description = "Enables the theme command without any pre-configured scope." +commands.allow = ["theme"] + +[[permission]] +identifier = "deny-theme" +description = "Denies the theme command without any pre-configured scope." +commands.deny = ["theme"] diff --git a/core/tauri/permissions/window/autogenerated/commands/title.toml b/core/tauri/permissions/window/autogenerated/commands/title.toml new file mode 100644 index 000000000000..67f05513ea09 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/title.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-title" +description = "Enables the title command without any pre-configured scope." +commands.allow = ["title"] + +[[permission]] +identifier = "deny-title" +description = "Denies the title command without any pre-configured scope." +commands.deny = ["title"] diff --git a/core/tauri/permissions/window/autogenerated/commands/toggle_maximize.toml b/core/tauri/permissions/window/autogenerated/commands/toggle_maximize.toml new file mode 100644 index 000000000000..1631c8932ee6 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/toggle_maximize.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-toggle-maximize" +description = "Enables the toggle_maximize command without any pre-configured scope." +commands.allow = ["toggle_maximize"] + +[[permission]] +identifier = "deny-toggle-maximize" +description = "Denies the toggle_maximize command without any pre-configured scope." +commands.deny = ["toggle_maximize"] diff --git a/core/tauri/permissions/window/autogenerated/commands/unmaximize.toml b/core/tauri/permissions/window/autogenerated/commands/unmaximize.toml new file mode 100644 index 000000000000..1a6a9b341ead --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/unmaximize.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-unmaximize" +description = "Enables the unmaximize command without any pre-configured scope." +commands.allow = ["unmaximize"] + +[[permission]] +identifier = "deny-unmaximize" +description = "Denies the unmaximize command without any pre-configured scope." +commands.deny = ["unmaximize"] diff --git a/core/tauri/permissions/window/autogenerated/commands/unminimize.toml b/core/tauri/permissions/window/autogenerated/commands/unminimize.toml new file mode 100644 index 000000000000..e527c5cd4298 --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/commands/unminimize.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../../.schema.json" + +[[permission]] +identifier = "allow-unminimize" +description = "Enables the unminimize command without any pre-configured scope." +commands.allow = ["unminimize"] + +[[permission]] +identifier = "deny-unminimize" +description = "Denies the unminimize command without any pre-configured scope." +commands.deny = ["unminimize"] diff --git a/core/tauri/permissions/window/autogenerated/default.toml b/core/tauri/permissions/window/autogenerated/default.toml new file mode 100644 index 000000000000..a3382c44ffdb --- /dev/null +++ b/core/tauri/permissions/window/autogenerated/default.toml @@ -0,0 +1,5 @@ +# Automatically generated - DO NOT EDIT! + +[default] +description = "Default permissions for the plugin." +permissions = ["allow-scale-factor", "allow-inner-position", "allow-outer-position", "allow-inner-size", "allow-outer-size", "allow-is-fullscreen", "allow-is-minimized", "allow-is-maximized", "allow-is-focused", "allow-is-decorated", "allow-is-resizable", "allow-is-maximizable", "allow-is-minimizable", "allow-is-closable", "allow-is-visible", "allow-title", "allow-current-monitor", "allow-primary-monitor", "allow-available-monitors", "allow-theme", "allow-internal-toggle-maximize", "allow-internal-toggle-devtools"] diff --git a/core/tauri/src/menu/plugin.rs b/core/tauri/src/menu/plugin.rs index ad10c4d9e6e6..10e2976ba150 100644 --- a/core/tauri/src/menu/plugin.rs +++ b/core/tauri/src/menu/plugin.rs @@ -661,7 +661,7 @@ async fn popup( } #[command(root = "crate")] -fn default(app: AppHandle) -> crate::Result<(ResourceId, MenuId)> { +fn create_default(app: AppHandle) -> crate::Result<(ResourceId, MenuId)> { let mut resources_table = app.resources_table(); let menu = Menu::default(&app)?; let id = menu.id().clone(); @@ -858,7 +858,7 @@ pub(crate) fn init() -> TauriPlugin { items, get, popup, - default, + create_default, set_as_app_menu, set_as_window_menu, text, diff --git a/core/tests/acl/src/lib.rs b/core/tests/acl/src/lib.rs index b030b2af51b4..91119b95f76c 100644 --- a/core/tests/acl/src/lib.rs +++ b/core/tests/acl/src/lib.rs @@ -15,9 +15,11 @@ mod tests { for plugin in plugins { let plugin_path = manifest_dir.join("fixtures").join("plugins").join(plugin); - let permission_files = - tauri_utils::acl::build::define_permissions(&format!("{}/*.toml", plugin_path.display())) - .expect("failed to define permissions"); + let permission_files = tauri_utils::acl::build::define_permissions( + &format!("{}/*.toml", plugin_path.display()), + plugin, + ) + .expect("failed to define permissions"); let manifest = Manifest::from_files(permission_files); manifests.insert(plugin.to_string(), manifest); } diff --git a/examples/api/src-tauri/capabilities/run-app.toml b/examples/api/src-tauri/capabilities/run-app.toml index 02ab69258f0b..a392dcb54a18 100644 --- a/examples/api/src-tauri/capabilities/run-app.toml +++ b/examples/api/src-tauri/capabilities/run-app.toml @@ -2,4 +2,14 @@ identifier = "run-app" description = "app capability" windows = ["main"] -permissions = ["sample:allow-ping-scoped", "sample:global-scope"] +permissions = [ + "path:default", + "event:default", + "window:default", + "app:default", + "resources:default", + "menu:default", + "tray:default", + "sample:allow-ping-scoped", + "sample:global-scope", +] diff --git a/tooling/api/src/menu/menu.ts b/tooling/api/src/menu/menu.ts index a4120cbde061..7ede3a98a0cc 100644 --- a/tooling/api/src/menu/menu.ts +++ b/tooling/api/src/menu/menu.ts @@ -82,7 +82,7 @@ export class Menu extends MenuItemBase { /** Create a default menu. */ static async default(): Promise { - return invoke<[number, string]>('plugin:menu|default').then( + return invoke<[number, string]>('plugin:menu|create_default').then( ([rid, id]) => new Menu(rid, id) ) } From faae4838eb4a3b8ac7ad5ba3e7b185e67971537a Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 17 Jan 2024 12:56:53 -0300 Subject: [PATCH 47/69] license headers --- core/tauri-plugin/src/build/mod.rs | 2 +- core/tauri-utils/src/acl/build.rs | 4 ++-- core/tauri/build.rs | 8 +++++++- .../permissions/app/autogenerated/commands/app_hide.toml | 3 +++ .../permissions/app/autogenerated/commands/app_show.toml | 3 +++ .../permissions/app/autogenerated/commands/name.toml | 3 +++ .../app/autogenerated/commands/tauri_version.toml | 3 +++ .../permissions/app/autogenerated/commands/version.toml | 3 +++ core/tauri/permissions/app/autogenerated/default.toml | 3 +++ .../permissions/event/autogenerated/commands/emit.toml | 3 +++ .../permissions/event/autogenerated/commands/listen.toml | 3 +++ .../event/autogenerated/commands/unlisten.toml | 3 +++ core/tauri/permissions/event/autogenerated/default.toml | 3 +++ .../permissions/menu/autogenerated/commands/append.toml | 3 +++ .../menu/autogenerated/commands/create_default.toml | 3 +++ .../permissions/menu/autogenerated/commands/get.toml | 3 +++ .../permissions/menu/autogenerated/commands/insert.toml | 3 +++ .../menu/autogenerated/commands/is_checked.toml | 3 +++ .../menu/autogenerated/commands/is_enabled.toml | 3 +++ .../permissions/menu/autogenerated/commands/items.toml | 3 +++ .../permissions/menu/autogenerated/commands/new.toml | 3 +++ .../permissions/menu/autogenerated/commands/popup.toml | 3 +++ .../permissions/menu/autogenerated/commands/prepend.toml | 3 +++ .../permissions/menu/autogenerated/commands/remove.toml | 3 +++ .../menu/autogenerated/commands/remove_at.toml | 3 +++ .../menu/autogenerated/commands/set_accelerator.toml | 3 +++ .../menu/autogenerated/commands/set_as_app_menu.toml | 3 +++ .../commands/set_as_help_menu_for_nsapp.toml | 3 +++ .../menu/autogenerated/commands/set_as_window_menu.toml | 3 +++ .../commands/set_as_windows_menu_for_nsapp.toml | 3 +++ .../menu/autogenerated/commands/set_checked.toml | 3 +++ .../menu/autogenerated/commands/set_enabled.toml | 3 +++ .../permissions/menu/autogenerated/commands/set_icon.toml | 3 +++ .../permissions/menu/autogenerated/commands/set_text.toml | 3 +++ .../permissions/menu/autogenerated/commands/text.toml | 3 +++ core/tauri/permissions/menu/autogenerated/default.toml | 3 +++ .../permissions/path/autogenerated/commands/basename.toml | 3 +++ .../permissions/path/autogenerated/commands/dirname.toml | 3 +++ .../permissions/path/autogenerated/commands/extname.toml | 3 +++ .../path/autogenerated/commands/is_absolute.toml | 3 +++ .../permissions/path/autogenerated/commands/join.toml | 3 +++ .../path/autogenerated/commands/normalize.toml | 3 +++ .../permissions/path/autogenerated/commands/resolve.toml | 3 +++ .../path/autogenerated/commands/resolve_directory.toml | 3 +++ core/tauri/permissions/path/autogenerated/default.toml | 3 +++ .../resources/autogenerated/commands/close.toml | 3 +++ .../permissions/resources/autogenerated/default.toml | 3 +++ .../permissions/tray/autogenerated/commands/new.toml | 3 +++ .../permissions/tray/autogenerated/commands/set_icon.toml | 3 +++ .../tray/autogenerated/commands/set_icon_as_template.toml | 3 +++ .../permissions/tray/autogenerated/commands/set_menu.toml | 3 +++ .../commands/set_show_menu_on_left_click.toml | 3 +++ .../tray/autogenerated/commands/set_temp_dir_path.toml | 3 +++ .../tray/autogenerated/commands/set_title.toml | 3 +++ .../tray/autogenerated/commands/set_tooltip.toml | 3 +++ .../tray/autogenerated/commands/set_visible.toml | 3 +++ core/tauri/permissions/tray/autogenerated/default.toml | 3 +++ .../window/autogenerated/commands/available_monitors.toml | 3 +++ .../permissions/window/autogenerated/commands/center.toml | 3 +++ .../permissions/window/autogenerated/commands/close.toml | 3 +++ .../permissions/window/autogenerated/commands/create.toml | 3 +++ .../window/autogenerated/commands/current_monitor.toml | 3 +++ .../permissions/window/autogenerated/commands/hide.toml | 3 +++ .../window/autogenerated/commands/inner_position.toml | 3 +++ .../window/autogenerated/commands/inner_size.toml | 3 +++ .../autogenerated/commands/internal_toggle_devtools.toml | 3 +++ .../autogenerated/commands/internal_toggle_maximize.toml | 3 +++ .../window/autogenerated/commands/is_closable.toml | 3 +++ .../window/autogenerated/commands/is_decorated.toml | 3 +++ .../window/autogenerated/commands/is_focused.toml | 3 +++ .../window/autogenerated/commands/is_fullscreen.toml | 3 +++ .../window/autogenerated/commands/is_maximizable.toml | 3 +++ .../window/autogenerated/commands/is_maximized.toml | 3 +++ .../window/autogenerated/commands/is_minimizable.toml | 3 +++ .../window/autogenerated/commands/is_minimized.toml | 3 +++ .../window/autogenerated/commands/is_resizable.toml | 3 +++ .../window/autogenerated/commands/is_visible.toml | 3 +++ .../window/autogenerated/commands/maximize.toml | 3 +++ .../window/autogenerated/commands/minimize.toml | 3 +++ .../window/autogenerated/commands/outer_position.toml | 3 +++ .../window/autogenerated/commands/outer_size.toml | 3 +++ .../window/autogenerated/commands/primary_monitor.toml | 3 +++ .../permissions/window/autogenerated/commands/print.toml | 3 +++ .../autogenerated/commands/request_user_attention.toml | 3 +++ .../window/autogenerated/commands/scale_factor.toml | 3 +++ .../autogenerated/commands/set_always_on_bottom.toml | 3 +++ .../window/autogenerated/commands/set_always_on_top.toml | 3 +++ .../window/autogenerated/commands/set_closable.toml | 3 +++ .../autogenerated/commands/set_content_protected.toml | 3 +++ .../window/autogenerated/commands/set_cursor_grab.toml | 3 +++ .../window/autogenerated/commands/set_cursor_icon.toml | 3 +++ .../autogenerated/commands/set_cursor_position.toml | 3 +++ .../window/autogenerated/commands/set_cursor_visible.toml | 3 +++ .../window/autogenerated/commands/set_decorations.toml | 3 +++ .../window/autogenerated/commands/set_effects.toml | 3 +++ .../window/autogenerated/commands/set_focus.toml | 3 +++ .../window/autogenerated/commands/set_fullscreen.toml | 3 +++ .../window/autogenerated/commands/set_icon.toml | 3 +++ .../autogenerated/commands/set_ignore_cursor_events.toml | 3 +++ .../window/autogenerated/commands/set_max_size.toml | 3 +++ .../window/autogenerated/commands/set_maximizable.toml | 3 +++ .../window/autogenerated/commands/set_min_size.toml | 3 +++ .../window/autogenerated/commands/set_minimizable.toml | 3 +++ .../window/autogenerated/commands/set_position.toml | 3 +++ .../window/autogenerated/commands/set_progress_bar.toml | 3 +++ .../window/autogenerated/commands/set_resizable.toml | 3 +++ .../window/autogenerated/commands/set_shadow.toml | 3 +++ .../window/autogenerated/commands/set_size.toml | 3 +++ .../window/autogenerated/commands/set_skip_taskbar.toml | 3 +++ .../window/autogenerated/commands/set_title.toml | 3 +++ .../permissions/window/autogenerated/commands/show.toml | 3 +++ .../window/autogenerated/commands/start_dragging.toml | 3 +++ .../permissions/window/autogenerated/commands/theme.toml | 3 +++ .../permissions/window/autogenerated/commands/title.toml | 3 +++ .../window/autogenerated/commands/toggle_maximize.toml | 3 +++ .../window/autogenerated/commands/unmaximize.toml | 3 +++ .../window/autogenerated/commands/unminimize.toml | 3 +++ core/tauri/permissions/window/autogenerated/default.toml | 3 +++ core/tests/acl/src/lib.rs | 4 ++++ 119 files changed, 359 insertions(+), 4 deletions(-) diff --git a/core/tauri-plugin/src/build/mod.rs b/core/tauri-plugin/src/build/mod.rs index b6b8b21dc82c..282c8a1115ad 100644 --- a/core/tauri-plugin/src/build/mod.rs +++ b/core/tauri-plugin/src/build/mod.rs @@ -44,7 +44,7 @@ impl<'a> Builder<'a> { let commands_dir = &autogenerated.join("commands"); if !self.commands.is_empty() { - acl::build::autogenerate_command_permissions(commands_dir, self.commands); + acl::build::autogenerate_command_permissions(commands_dir, self.commands, ""); } let permissions = acl::build::define_permissions( diff --git a/core/tauri-utils/src/acl/build.rs b/core/tauri-utils/src/acl/build.rs index 8360626b6969..491f0e76445d 100644 --- a/core/tauri-utils/src/acl/build.rs +++ b/core/tauri-utils/src/acl/build.rs @@ -276,7 +276,7 @@ fn parse_permissions(paths: Vec) -> Result, Error> } /// Autogenerate permission files for a list of commands. -pub fn autogenerate_command_permissions(path: &Path, commands: &[&str]) { +pub fn autogenerate_command_permissions(path: &Path, commands: &[&str], license_header: &str) { if !path.exists() { create_dir_all(path).expect("unable to create autogenerated commands dir"); } @@ -291,7 +291,7 @@ pub fn autogenerate_command_permissions(path: &Path, commands: &[&str]) { for command in commands { let slugified_command = command.replace('_', "-"); let toml = format!( - r###"# Automatically generated - DO NOT EDIT! + r###"{license_header}# Automatically generated - DO NOT EDIT! "$schema" = "{schema_path}" diff --git a/core/tauri/build.rs b/core/tauri/build.rs index 3136aabc3eb1..5739c88f5d71 100644 --- a/core/tauri/build.rs +++ b/core/tauri/build.rs @@ -279,6 +279,11 @@ fn main() { } fn define_permissions() { + let license_header = r#"# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT +"#; + for (plugin, commands) in PLUGINS { let autogenerated = PathBuf::from(format!("permissions/{plugin}/autogenerated/")); let commands_dir = autogenerated.join("commands"); @@ -286,6 +291,7 @@ fn define_permissions() { tauri_utils::acl::build::autogenerate_command_permissions( &commands_dir, &commands.iter().map(|(cmd, _)| *cmd).collect::>(), + license_header, ); let default_permissions = commands .iter() @@ -298,7 +304,7 @@ fn define_permissions() { .join(", "); let default_toml = format!( - r###"# Automatically generated - DO NOT EDIT! + r###"{license_header}# Automatically generated - DO NOT EDIT! [default] description = "Default permissions for the plugin." diff --git a/core/tauri/permissions/app/autogenerated/commands/app_hide.toml b/core/tauri/permissions/app/autogenerated/commands/app_hide.toml index e29f148d8fe4..00c3297eda95 100644 --- a/core/tauri/permissions/app/autogenerated/commands/app_hide.toml +++ b/core/tauri/permissions/app/autogenerated/commands/app_hide.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/app/autogenerated/commands/app_show.toml b/core/tauri/permissions/app/autogenerated/commands/app_show.toml index ec77dc52d3b5..b93047123134 100644 --- a/core/tauri/permissions/app/autogenerated/commands/app_show.toml +++ b/core/tauri/permissions/app/autogenerated/commands/app_show.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/app/autogenerated/commands/name.toml b/core/tauri/permissions/app/autogenerated/commands/name.toml index b5cc148938ca..859a0209a9da 100644 --- a/core/tauri/permissions/app/autogenerated/commands/name.toml +++ b/core/tauri/permissions/app/autogenerated/commands/name.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/app/autogenerated/commands/tauri_version.toml b/core/tauri/permissions/app/autogenerated/commands/tauri_version.toml index 5c4a41efd03f..3e71c771b9f2 100644 --- a/core/tauri/permissions/app/autogenerated/commands/tauri_version.toml +++ b/core/tauri/permissions/app/autogenerated/commands/tauri_version.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/app/autogenerated/commands/version.toml b/core/tauri/permissions/app/autogenerated/commands/version.toml index c33b4a4a1ada..4a50bddeda20 100644 --- a/core/tauri/permissions/app/autogenerated/commands/version.toml +++ b/core/tauri/permissions/app/autogenerated/commands/version.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/app/autogenerated/default.toml b/core/tauri/permissions/app/autogenerated/default.toml index 0896c91a68be..a614e4d18e6c 100644 --- a/core/tauri/permissions/app/autogenerated/default.toml +++ b/core/tauri/permissions/app/autogenerated/default.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! [default] diff --git a/core/tauri/permissions/event/autogenerated/commands/emit.toml b/core/tauri/permissions/event/autogenerated/commands/emit.toml index db6ef6e09d33..4b0d4048b179 100644 --- a/core/tauri/permissions/event/autogenerated/commands/emit.toml +++ b/core/tauri/permissions/event/autogenerated/commands/emit.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/event/autogenerated/commands/listen.toml b/core/tauri/permissions/event/autogenerated/commands/listen.toml index f32005b07179..8732753ef5d7 100644 --- a/core/tauri/permissions/event/autogenerated/commands/listen.toml +++ b/core/tauri/permissions/event/autogenerated/commands/listen.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/event/autogenerated/commands/unlisten.toml b/core/tauri/permissions/event/autogenerated/commands/unlisten.toml index 2a01c4cafc93..86b0595d55cf 100644 --- a/core/tauri/permissions/event/autogenerated/commands/unlisten.toml +++ b/core/tauri/permissions/event/autogenerated/commands/unlisten.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/event/autogenerated/default.toml b/core/tauri/permissions/event/autogenerated/default.toml index 8c627d632d52..5c608785857d 100644 --- a/core/tauri/permissions/event/autogenerated/default.toml +++ b/core/tauri/permissions/event/autogenerated/default.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! [default] diff --git a/core/tauri/permissions/menu/autogenerated/commands/append.toml b/core/tauri/permissions/menu/autogenerated/commands/append.toml index 4af693b62322..f370284b42a3 100644 --- a/core/tauri/permissions/menu/autogenerated/commands/append.toml +++ b/core/tauri/permissions/menu/autogenerated/commands/append.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/menu/autogenerated/commands/create_default.toml b/core/tauri/permissions/menu/autogenerated/commands/create_default.toml index 0c88974a52a5..ce51b421a6da 100644 --- a/core/tauri/permissions/menu/autogenerated/commands/create_default.toml +++ b/core/tauri/permissions/menu/autogenerated/commands/create_default.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/menu/autogenerated/commands/get.toml b/core/tauri/permissions/menu/autogenerated/commands/get.toml index 4aeb868b8641..79a5620fd544 100644 --- a/core/tauri/permissions/menu/autogenerated/commands/get.toml +++ b/core/tauri/permissions/menu/autogenerated/commands/get.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/menu/autogenerated/commands/insert.toml b/core/tauri/permissions/menu/autogenerated/commands/insert.toml index e204edbc7f55..5de90c3c84a9 100644 --- a/core/tauri/permissions/menu/autogenerated/commands/insert.toml +++ b/core/tauri/permissions/menu/autogenerated/commands/insert.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/menu/autogenerated/commands/is_checked.toml b/core/tauri/permissions/menu/autogenerated/commands/is_checked.toml index ea05872dd94d..efb4299a1bed 100644 --- a/core/tauri/permissions/menu/autogenerated/commands/is_checked.toml +++ b/core/tauri/permissions/menu/autogenerated/commands/is_checked.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/menu/autogenerated/commands/is_enabled.toml b/core/tauri/permissions/menu/autogenerated/commands/is_enabled.toml index 10741b37c6c1..39b567085f11 100644 --- a/core/tauri/permissions/menu/autogenerated/commands/is_enabled.toml +++ b/core/tauri/permissions/menu/autogenerated/commands/is_enabled.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/menu/autogenerated/commands/items.toml b/core/tauri/permissions/menu/autogenerated/commands/items.toml index c87f128d507b..cbb5055007cf 100644 --- a/core/tauri/permissions/menu/autogenerated/commands/items.toml +++ b/core/tauri/permissions/menu/autogenerated/commands/items.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/menu/autogenerated/commands/new.toml b/core/tauri/permissions/menu/autogenerated/commands/new.toml index a8db386c0558..c87453714563 100644 --- a/core/tauri/permissions/menu/autogenerated/commands/new.toml +++ b/core/tauri/permissions/menu/autogenerated/commands/new.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/menu/autogenerated/commands/popup.toml b/core/tauri/permissions/menu/autogenerated/commands/popup.toml index df17be75f524..18970ba64117 100644 --- a/core/tauri/permissions/menu/autogenerated/commands/popup.toml +++ b/core/tauri/permissions/menu/autogenerated/commands/popup.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/menu/autogenerated/commands/prepend.toml b/core/tauri/permissions/menu/autogenerated/commands/prepend.toml index e7df4dbdabea..5c90aba3d080 100644 --- a/core/tauri/permissions/menu/autogenerated/commands/prepend.toml +++ b/core/tauri/permissions/menu/autogenerated/commands/prepend.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/menu/autogenerated/commands/remove.toml b/core/tauri/permissions/menu/autogenerated/commands/remove.toml index 99f3eb665683..c7e09c5904fe 100644 --- a/core/tauri/permissions/menu/autogenerated/commands/remove.toml +++ b/core/tauri/permissions/menu/autogenerated/commands/remove.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/menu/autogenerated/commands/remove_at.toml b/core/tauri/permissions/menu/autogenerated/commands/remove_at.toml index 4acea0d6364d..3a58bc731d2c 100644 --- a/core/tauri/permissions/menu/autogenerated/commands/remove_at.toml +++ b/core/tauri/permissions/menu/autogenerated/commands/remove_at.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/menu/autogenerated/commands/set_accelerator.toml b/core/tauri/permissions/menu/autogenerated/commands/set_accelerator.toml index 02cb03f662b1..9392a0dbdc1f 100644 --- a/core/tauri/permissions/menu/autogenerated/commands/set_accelerator.toml +++ b/core/tauri/permissions/menu/autogenerated/commands/set_accelerator.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/menu/autogenerated/commands/set_as_app_menu.toml b/core/tauri/permissions/menu/autogenerated/commands/set_as_app_menu.toml index 6a0ac4639816..fa838d50086b 100644 --- a/core/tauri/permissions/menu/autogenerated/commands/set_as_app_menu.toml +++ b/core/tauri/permissions/menu/autogenerated/commands/set_as_app_menu.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/menu/autogenerated/commands/set_as_help_menu_for_nsapp.toml b/core/tauri/permissions/menu/autogenerated/commands/set_as_help_menu_for_nsapp.toml index 36b0ecd244b4..c90644a8ef93 100644 --- a/core/tauri/permissions/menu/autogenerated/commands/set_as_help_menu_for_nsapp.toml +++ b/core/tauri/permissions/menu/autogenerated/commands/set_as_help_menu_for_nsapp.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/menu/autogenerated/commands/set_as_window_menu.toml b/core/tauri/permissions/menu/autogenerated/commands/set_as_window_menu.toml index 714c1e472672..1e0c7fd240f0 100644 --- a/core/tauri/permissions/menu/autogenerated/commands/set_as_window_menu.toml +++ b/core/tauri/permissions/menu/autogenerated/commands/set_as_window_menu.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/menu/autogenerated/commands/set_as_windows_menu_for_nsapp.toml b/core/tauri/permissions/menu/autogenerated/commands/set_as_windows_menu_for_nsapp.toml index 9614aaa2c5a0..3583ccd2786c 100644 --- a/core/tauri/permissions/menu/autogenerated/commands/set_as_windows_menu_for_nsapp.toml +++ b/core/tauri/permissions/menu/autogenerated/commands/set_as_windows_menu_for_nsapp.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/menu/autogenerated/commands/set_checked.toml b/core/tauri/permissions/menu/autogenerated/commands/set_checked.toml index 4be3e4453c32..784b85da9b52 100644 --- a/core/tauri/permissions/menu/autogenerated/commands/set_checked.toml +++ b/core/tauri/permissions/menu/autogenerated/commands/set_checked.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/menu/autogenerated/commands/set_enabled.toml b/core/tauri/permissions/menu/autogenerated/commands/set_enabled.toml index 0b085e3af5ff..76a3df65209c 100644 --- a/core/tauri/permissions/menu/autogenerated/commands/set_enabled.toml +++ b/core/tauri/permissions/menu/autogenerated/commands/set_enabled.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/menu/autogenerated/commands/set_icon.toml b/core/tauri/permissions/menu/autogenerated/commands/set_icon.toml index 408288069419..556648a688bc 100644 --- a/core/tauri/permissions/menu/autogenerated/commands/set_icon.toml +++ b/core/tauri/permissions/menu/autogenerated/commands/set_icon.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/menu/autogenerated/commands/set_text.toml b/core/tauri/permissions/menu/autogenerated/commands/set_text.toml index 793ae2243209..5a050e3c38fc 100644 --- a/core/tauri/permissions/menu/autogenerated/commands/set_text.toml +++ b/core/tauri/permissions/menu/autogenerated/commands/set_text.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/menu/autogenerated/commands/text.toml b/core/tauri/permissions/menu/autogenerated/commands/text.toml index 108f8dbcd416..a6c5b93261e6 100644 --- a/core/tauri/permissions/menu/autogenerated/commands/text.toml +++ b/core/tauri/permissions/menu/autogenerated/commands/text.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/menu/autogenerated/default.toml b/core/tauri/permissions/menu/autogenerated/default.toml index 6887d8a2bb3c..6817a6290cbb 100644 --- a/core/tauri/permissions/menu/autogenerated/default.toml +++ b/core/tauri/permissions/menu/autogenerated/default.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! [default] diff --git a/core/tauri/permissions/path/autogenerated/commands/basename.toml b/core/tauri/permissions/path/autogenerated/commands/basename.toml index 280466f0710a..5be962c63c97 100644 --- a/core/tauri/permissions/path/autogenerated/commands/basename.toml +++ b/core/tauri/permissions/path/autogenerated/commands/basename.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/path/autogenerated/commands/dirname.toml b/core/tauri/permissions/path/autogenerated/commands/dirname.toml index ef7d234eaa58..94d2a1b9722f 100644 --- a/core/tauri/permissions/path/autogenerated/commands/dirname.toml +++ b/core/tauri/permissions/path/autogenerated/commands/dirname.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/path/autogenerated/commands/extname.toml b/core/tauri/permissions/path/autogenerated/commands/extname.toml index 92771bb4ac6b..ba628fcad70a 100644 --- a/core/tauri/permissions/path/autogenerated/commands/extname.toml +++ b/core/tauri/permissions/path/autogenerated/commands/extname.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/path/autogenerated/commands/is_absolute.toml b/core/tauri/permissions/path/autogenerated/commands/is_absolute.toml index dbd6d564bc2c..463de2f3a07a 100644 --- a/core/tauri/permissions/path/autogenerated/commands/is_absolute.toml +++ b/core/tauri/permissions/path/autogenerated/commands/is_absolute.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/path/autogenerated/commands/join.toml b/core/tauri/permissions/path/autogenerated/commands/join.toml index cf402e3e85cc..bc2aa3ce04ec 100644 --- a/core/tauri/permissions/path/autogenerated/commands/join.toml +++ b/core/tauri/permissions/path/autogenerated/commands/join.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/path/autogenerated/commands/normalize.toml b/core/tauri/permissions/path/autogenerated/commands/normalize.toml index 4a1f4fe295e6..7c18e091390d 100644 --- a/core/tauri/permissions/path/autogenerated/commands/normalize.toml +++ b/core/tauri/permissions/path/autogenerated/commands/normalize.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/path/autogenerated/commands/resolve.toml b/core/tauri/permissions/path/autogenerated/commands/resolve.toml index bcae8ee6a10c..f4223bf6ad89 100644 --- a/core/tauri/permissions/path/autogenerated/commands/resolve.toml +++ b/core/tauri/permissions/path/autogenerated/commands/resolve.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/path/autogenerated/commands/resolve_directory.toml b/core/tauri/permissions/path/autogenerated/commands/resolve_directory.toml index 2bbd9186d0ce..6a207cfca6c7 100644 --- a/core/tauri/permissions/path/autogenerated/commands/resolve_directory.toml +++ b/core/tauri/permissions/path/autogenerated/commands/resolve_directory.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/path/autogenerated/default.toml b/core/tauri/permissions/path/autogenerated/default.toml index 1d1748599a6c..637a878d68f3 100644 --- a/core/tauri/permissions/path/autogenerated/default.toml +++ b/core/tauri/permissions/path/autogenerated/default.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! [default] diff --git a/core/tauri/permissions/resources/autogenerated/commands/close.toml b/core/tauri/permissions/resources/autogenerated/commands/close.toml index 1df7316c8d97..ddbc008d0dea 100644 --- a/core/tauri/permissions/resources/autogenerated/commands/close.toml +++ b/core/tauri/permissions/resources/autogenerated/commands/close.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/resources/autogenerated/default.toml b/core/tauri/permissions/resources/autogenerated/default.toml index baf14d674d79..46686da50f24 100644 --- a/core/tauri/permissions/resources/autogenerated/default.toml +++ b/core/tauri/permissions/resources/autogenerated/default.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! [default] diff --git a/core/tauri/permissions/tray/autogenerated/commands/new.toml b/core/tauri/permissions/tray/autogenerated/commands/new.toml index a8db386c0558..c87453714563 100644 --- a/core/tauri/permissions/tray/autogenerated/commands/new.toml +++ b/core/tauri/permissions/tray/autogenerated/commands/new.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/tray/autogenerated/commands/set_icon.toml b/core/tauri/permissions/tray/autogenerated/commands/set_icon.toml index 408288069419..556648a688bc 100644 --- a/core/tauri/permissions/tray/autogenerated/commands/set_icon.toml +++ b/core/tauri/permissions/tray/autogenerated/commands/set_icon.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/tray/autogenerated/commands/set_icon_as_template.toml b/core/tauri/permissions/tray/autogenerated/commands/set_icon_as_template.toml index 329e1f72ba0e..1798118c44f5 100644 --- a/core/tauri/permissions/tray/autogenerated/commands/set_icon_as_template.toml +++ b/core/tauri/permissions/tray/autogenerated/commands/set_icon_as_template.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/tray/autogenerated/commands/set_menu.toml b/core/tauri/permissions/tray/autogenerated/commands/set_menu.toml index 1a58a064fbb9..b23bba10e5f3 100644 --- a/core/tauri/permissions/tray/autogenerated/commands/set_menu.toml +++ b/core/tauri/permissions/tray/autogenerated/commands/set_menu.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/tray/autogenerated/commands/set_show_menu_on_left_click.toml b/core/tauri/permissions/tray/autogenerated/commands/set_show_menu_on_left_click.toml index e5fd9774beca..a6209b628468 100644 --- a/core/tauri/permissions/tray/autogenerated/commands/set_show_menu_on_left_click.toml +++ b/core/tauri/permissions/tray/autogenerated/commands/set_show_menu_on_left_click.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/tray/autogenerated/commands/set_temp_dir_path.toml b/core/tauri/permissions/tray/autogenerated/commands/set_temp_dir_path.toml index 4c3510af9bed..e07000aa6ae6 100644 --- a/core/tauri/permissions/tray/autogenerated/commands/set_temp_dir_path.toml +++ b/core/tauri/permissions/tray/autogenerated/commands/set_temp_dir_path.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/tray/autogenerated/commands/set_title.toml b/core/tauri/permissions/tray/autogenerated/commands/set_title.toml index 872f35577bbe..b522982eb117 100644 --- a/core/tauri/permissions/tray/autogenerated/commands/set_title.toml +++ b/core/tauri/permissions/tray/autogenerated/commands/set_title.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/tray/autogenerated/commands/set_tooltip.toml b/core/tauri/permissions/tray/autogenerated/commands/set_tooltip.toml index 5a80dd195404..64434654cc96 100644 --- a/core/tauri/permissions/tray/autogenerated/commands/set_tooltip.toml +++ b/core/tauri/permissions/tray/autogenerated/commands/set_tooltip.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/tray/autogenerated/commands/set_visible.toml b/core/tauri/permissions/tray/autogenerated/commands/set_visible.toml index f88d57ed30fc..ff92c3869a39 100644 --- a/core/tauri/permissions/tray/autogenerated/commands/set_visible.toml +++ b/core/tauri/permissions/tray/autogenerated/commands/set_visible.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/tray/autogenerated/default.toml b/core/tauri/permissions/tray/autogenerated/default.toml index 6887d8a2bb3c..6817a6290cbb 100644 --- a/core/tauri/permissions/tray/autogenerated/default.toml +++ b/core/tauri/permissions/tray/autogenerated/default.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! [default] diff --git a/core/tauri/permissions/window/autogenerated/commands/available_monitors.toml b/core/tauri/permissions/window/autogenerated/commands/available_monitors.toml index 34ec3287aacd..78460c8f817d 100644 --- a/core/tauri/permissions/window/autogenerated/commands/available_monitors.toml +++ b/core/tauri/permissions/window/autogenerated/commands/available_monitors.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/center.toml b/core/tauri/permissions/window/autogenerated/commands/center.toml index 75d71f775291..c66d4ad08b55 100644 --- a/core/tauri/permissions/window/autogenerated/commands/center.toml +++ b/core/tauri/permissions/window/autogenerated/commands/center.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/close.toml b/core/tauri/permissions/window/autogenerated/commands/close.toml index 1df7316c8d97..ddbc008d0dea 100644 --- a/core/tauri/permissions/window/autogenerated/commands/close.toml +++ b/core/tauri/permissions/window/autogenerated/commands/close.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/create.toml b/core/tauri/permissions/window/autogenerated/commands/create.toml index af9db7b368a7..db39506f5c4a 100644 --- a/core/tauri/permissions/window/autogenerated/commands/create.toml +++ b/core/tauri/permissions/window/autogenerated/commands/create.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/current_monitor.toml b/core/tauri/permissions/window/autogenerated/commands/current_monitor.toml index 79d0870c8e1b..543e81cf0466 100644 --- a/core/tauri/permissions/window/autogenerated/commands/current_monitor.toml +++ b/core/tauri/permissions/window/autogenerated/commands/current_monitor.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/hide.toml b/core/tauri/permissions/window/autogenerated/commands/hide.toml index 331c3b18b645..7baddd5dec1d 100644 --- a/core/tauri/permissions/window/autogenerated/commands/hide.toml +++ b/core/tauri/permissions/window/autogenerated/commands/hide.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/inner_position.toml b/core/tauri/permissions/window/autogenerated/commands/inner_position.toml index 67e6872fe3c0..418b9b675a36 100644 --- a/core/tauri/permissions/window/autogenerated/commands/inner_position.toml +++ b/core/tauri/permissions/window/autogenerated/commands/inner_position.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/inner_size.toml b/core/tauri/permissions/window/autogenerated/commands/inner_size.toml index 8f7ae0f22fc6..313b4df62543 100644 --- a/core/tauri/permissions/window/autogenerated/commands/inner_size.toml +++ b/core/tauri/permissions/window/autogenerated/commands/inner_size.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/internal_toggle_devtools.toml b/core/tauri/permissions/window/autogenerated/commands/internal_toggle_devtools.toml index a8474bd2ac82..85e19e75009f 100644 --- a/core/tauri/permissions/window/autogenerated/commands/internal_toggle_devtools.toml +++ b/core/tauri/permissions/window/autogenerated/commands/internal_toggle_devtools.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/internal_toggle_maximize.toml b/core/tauri/permissions/window/autogenerated/commands/internal_toggle_maximize.toml index fd1dd4c54294..4f663c0bed82 100644 --- a/core/tauri/permissions/window/autogenerated/commands/internal_toggle_maximize.toml +++ b/core/tauri/permissions/window/autogenerated/commands/internal_toggle_maximize.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/is_closable.toml b/core/tauri/permissions/window/autogenerated/commands/is_closable.toml index 6d0a9e921a64..fe9d94256084 100644 --- a/core/tauri/permissions/window/autogenerated/commands/is_closable.toml +++ b/core/tauri/permissions/window/autogenerated/commands/is_closable.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/is_decorated.toml b/core/tauri/permissions/window/autogenerated/commands/is_decorated.toml index 50f284ed45a8..a8f2055b0698 100644 --- a/core/tauri/permissions/window/autogenerated/commands/is_decorated.toml +++ b/core/tauri/permissions/window/autogenerated/commands/is_decorated.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/is_focused.toml b/core/tauri/permissions/window/autogenerated/commands/is_focused.toml index e8b9b6f92abd..e58975d235a9 100644 --- a/core/tauri/permissions/window/autogenerated/commands/is_focused.toml +++ b/core/tauri/permissions/window/autogenerated/commands/is_focused.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/is_fullscreen.toml b/core/tauri/permissions/window/autogenerated/commands/is_fullscreen.toml index c870464626f3..28db27d3818f 100644 --- a/core/tauri/permissions/window/autogenerated/commands/is_fullscreen.toml +++ b/core/tauri/permissions/window/autogenerated/commands/is_fullscreen.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/is_maximizable.toml b/core/tauri/permissions/window/autogenerated/commands/is_maximizable.toml index 0e1888e5c137..4ac0bc946be9 100644 --- a/core/tauri/permissions/window/autogenerated/commands/is_maximizable.toml +++ b/core/tauri/permissions/window/autogenerated/commands/is_maximizable.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/is_maximized.toml b/core/tauri/permissions/window/autogenerated/commands/is_maximized.toml index 655d3e3c313d..c35dbd38470b 100644 --- a/core/tauri/permissions/window/autogenerated/commands/is_maximized.toml +++ b/core/tauri/permissions/window/autogenerated/commands/is_maximized.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/is_minimizable.toml b/core/tauri/permissions/window/autogenerated/commands/is_minimizable.toml index fb3b85c1dbd7..073da07c8dc0 100644 --- a/core/tauri/permissions/window/autogenerated/commands/is_minimizable.toml +++ b/core/tauri/permissions/window/autogenerated/commands/is_minimizable.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/is_minimized.toml b/core/tauri/permissions/window/autogenerated/commands/is_minimized.toml index 88dc3c189a63..22b5685c877d 100644 --- a/core/tauri/permissions/window/autogenerated/commands/is_minimized.toml +++ b/core/tauri/permissions/window/autogenerated/commands/is_minimized.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/is_resizable.toml b/core/tauri/permissions/window/autogenerated/commands/is_resizable.toml index 760982c3b9b5..86e06c23f2b2 100644 --- a/core/tauri/permissions/window/autogenerated/commands/is_resizable.toml +++ b/core/tauri/permissions/window/autogenerated/commands/is_resizable.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/is_visible.toml b/core/tauri/permissions/window/autogenerated/commands/is_visible.toml index 3bce7072c829..214cd1d01740 100644 --- a/core/tauri/permissions/window/autogenerated/commands/is_visible.toml +++ b/core/tauri/permissions/window/autogenerated/commands/is_visible.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/maximize.toml b/core/tauri/permissions/window/autogenerated/commands/maximize.toml index 0e4d3be5b60b..69bf6e376e5a 100644 --- a/core/tauri/permissions/window/autogenerated/commands/maximize.toml +++ b/core/tauri/permissions/window/autogenerated/commands/maximize.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/minimize.toml b/core/tauri/permissions/window/autogenerated/commands/minimize.toml index fedb5b0086f9..f58399ab728e 100644 --- a/core/tauri/permissions/window/autogenerated/commands/minimize.toml +++ b/core/tauri/permissions/window/autogenerated/commands/minimize.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/outer_position.toml b/core/tauri/permissions/window/autogenerated/commands/outer_position.toml index 308d239b5e7a..1bd4cb597aab 100644 --- a/core/tauri/permissions/window/autogenerated/commands/outer_position.toml +++ b/core/tauri/permissions/window/autogenerated/commands/outer_position.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/outer_size.toml b/core/tauri/permissions/window/autogenerated/commands/outer_size.toml index 6e1b931255f2..962e66fc3058 100644 --- a/core/tauri/permissions/window/autogenerated/commands/outer_size.toml +++ b/core/tauri/permissions/window/autogenerated/commands/outer_size.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/primary_monitor.toml b/core/tauri/permissions/window/autogenerated/commands/primary_monitor.toml index 32baaac916c6..7493e5414fbd 100644 --- a/core/tauri/permissions/window/autogenerated/commands/primary_monitor.toml +++ b/core/tauri/permissions/window/autogenerated/commands/primary_monitor.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/print.toml b/core/tauri/permissions/window/autogenerated/commands/print.toml index 289a28f75fe5..820f5c33b840 100644 --- a/core/tauri/permissions/window/autogenerated/commands/print.toml +++ b/core/tauri/permissions/window/autogenerated/commands/print.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/request_user_attention.toml b/core/tauri/permissions/window/autogenerated/commands/request_user_attention.toml index 44bffe87f885..815c69bc928c 100644 --- a/core/tauri/permissions/window/autogenerated/commands/request_user_attention.toml +++ b/core/tauri/permissions/window/autogenerated/commands/request_user_attention.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/scale_factor.toml b/core/tauri/permissions/window/autogenerated/commands/scale_factor.toml index 73079e5e892d..ba07656f598c 100644 --- a/core/tauri/permissions/window/autogenerated/commands/scale_factor.toml +++ b/core/tauri/permissions/window/autogenerated/commands/scale_factor.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_always_on_bottom.toml b/core/tauri/permissions/window/autogenerated/commands/set_always_on_bottom.toml index f51731f0509d..2b4b9c4e10c1 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_always_on_bottom.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_always_on_bottom.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_always_on_top.toml b/core/tauri/permissions/window/autogenerated/commands/set_always_on_top.toml index 645742a989b4..709f2df837c1 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_always_on_top.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_always_on_top.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_closable.toml b/core/tauri/permissions/window/autogenerated/commands/set_closable.toml index 8f67794836c0..79fd5eebc1ab 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_closable.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_closable.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_content_protected.toml b/core/tauri/permissions/window/autogenerated/commands/set_content_protected.toml index 9948afdb8844..0641ee285acf 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_content_protected.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_content_protected.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_cursor_grab.toml b/core/tauri/permissions/window/autogenerated/commands/set_cursor_grab.toml index 962b37a41eee..455d0dd3b32b 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_cursor_grab.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_cursor_grab.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_cursor_icon.toml b/core/tauri/permissions/window/autogenerated/commands/set_cursor_icon.toml index 89eae85ba25f..e6ed6b099569 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_cursor_icon.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_cursor_icon.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_cursor_position.toml b/core/tauri/permissions/window/autogenerated/commands/set_cursor_position.toml index ad752b80d1bf..98ec27bb380c 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_cursor_position.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_cursor_position.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_cursor_visible.toml b/core/tauri/permissions/window/autogenerated/commands/set_cursor_visible.toml index 69ed51cd84e0..b2668a965598 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_cursor_visible.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_cursor_visible.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_decorations.toml b/core/tauri/permissions/window/autogenerated/commands/set_decorations.toml index 590a0c5dd12d..4db5281d7408 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_decorations.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_decorations.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_effects.toml b/core/tauri/permissions/window/autogenerated/commands/set_effects.toml index b957124875d7..16d707979713 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_effects.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_effects.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_focus.toml b/core/tauri/permissions/window/autogenerated/commands/set_focus.toml index ce4cbd12f3d9..79e6d81a3cc0 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_focus.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_focus.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_fullscreen.toml b/core/tauri/permissions/window/autogenerated/commands/set_fullscreen.toml index 34483410a552..9ff220fe60a5 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_fullscreen.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_fullscreen.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_icon.toml b/core/tauri/permissions/window/autogenerated/commands/set_icon.toml index 408288069419..556648a688bc 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_icon.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_icon.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_ignore_cursor_events.toml b/core/tauri/permissions/window/autogenerated/commands/set_ignore_cursor_events.toml index 55563130929f..c437a4be7284 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_ignore_cursor_events.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_ignore_cursor_events.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_max_size.toml b/core/tauri/permissions/window/autogenerated/commands/set_max_size.toml index 573e7bdead88..c08893fa4560 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_max_size.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_max_size.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_maximizable.toml b/core/tauri/permissions/window/autogenerated/commands/set_maximizable.toml index 45c6e1f764eb..b4d3c19222f8 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_maximizable.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_maximizable.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_min_size.toml b/core/tauri/permissions/window/autogenerated/commands/set_min_size.toml index 0a4d961890df..b168be30c7c7 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_min_size.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_min_size.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_minimizable.toml b/core/tauri/permissions/window/autogenerated/commands/set_minimizable.toml index 5e331b43baa9..727948c3935b 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_minimizable.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_minimizable.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_position.toml b/core/tauri/permissions/window/autogenerated/commands/set_position.toml index 068a577aa9b8..3ed75531b56b 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_position.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_position.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_progress_bar.toml b/core/tauri/permissions/window/autogenerated/commands/set_progress_bar.toml index 0b9f68a197ca..dcf769e174a7 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_progress_bar.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_progress_bar.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_resizable.toml b/core/tauri/permissions/window/autogenerated/commands/set_resizable.toml index 50367b95f39e..f6fa71794d5c 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_resizable.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_resizable.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_shadow.toml b/core/tauri/permissions/window/autogenerated/commands/set_shadow.toml index f6a8536ebdfe..89bae03037dd 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_shadow.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_shadow.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_size.toml b/core/tauri/permissions/window/autogenerated/commands/set_size.toml index 4f1b86ce9c57..0b2dd25c2f28 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_size.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_size.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_skip_taskbar.toml b/core/tauri/permissions/window/autogenerated/commands/set_skip_taskbar.toml index 2a90116c48d2..ad5957c08571 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_skip_taskbar.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_skip_taskbar.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/set_title.toml b/core/tauri/permissions/window/autogenerated/commands/set_title.toml index 872f35577bbe..b522982eb117 100644 --- a/core/tauri/permissions/window/autogenerated/commands/set_title.toml +++ b/core/tauri/permissions/window/autogenerated/commands/set_title.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/show.toml b/core/tauri/permissions/window/autogenerated/commands/show.toml index 5ba13eb9bec7..ed84f065c642 100644 --- a/core/tauri/permissions/window/autogenerated/commands/show.toml +++ b/core/tauri/permissions/window/autogenerated/commands/show.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/start_dragging.toml b/core/tauri/permissions/window/autogenerated/commands/start_dragging.toml index 61e4e9cb789c..5864ae81e930 100644 --- a/core/tauri/permissions/window/autogenerated/commands/start_dragging.toml +++ b/core/tauri/permissions/window/autogenerated/commands/start_dragging.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/theme.toml b/core/tauri/permissions/window/autogenerated/commands/theme.toml index 4b7b4fd01733..09fdd772839b 100644 --- a/core/tauri/permissions/window/autogenerated/commands/theme.toml +++ b/core/tauri/permissions/window/autogenerated/commands/theme.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/title.toml b/core/tauri/permissions/window/autogenerated/commands/title.toml index 67f05513ea09..327dd30be247 100644 --- a/core/tauri/permissions/window/autogenerated/commands/title.toml +++ b/core/tauri/permissions/window/autogenerated/commands/title.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/toggle_maximize.toml b/core/tauri/permissions/window/autogenerated/commands/toggle_maximize.toml index 1631c8932ee6..01a601aa026c 100644 --- a/core/tauri/permissions/window/autogenerated/commands/toggle_maximize.toml +++ b/core/tauri/permissions/window/autogenerated/commands/toggle_maximize.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/unmaximize.toml b/core/tauri/permissions/window/autogenerated/commands/unmaximize.toml index 1a6a9b341ead..47701d92f6e4 100644 --- a/core/tauri/permissions/window/autogenerated/commands/unmaximize.toml +++ b/core/tauri/permissions/window/autogenerated/commands/unmaximize.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/commands/unminimize.toml b/core/tauri/permissions/window/autogenerated/commands/unminimize.toml index e527c5cd4298..abefddecd37e 100644 --- a/core/tauri/permissions/window/autogenerated/commands/unminimize.toml +++ b/core/tauri/permissions/window/autogenerated/commands/unminimize.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! "$schema" = "../../../.schema.json" diff --git a/core/tauri/permissions/window/autogenerated/default.toml b/core/tauri/permissions/window/autogenerated/default.toml index a3382c44ffdb..01559b388a0a 100644 --- a/core/tauri/permissions/window/autogenerated/default.toml +++ b/core/tauri/permissions/window/autogenerated/default.toml @@ -1,3 +1,6 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT # Automatically generated - DO NOT EDIT! [default] diff --git a/core/tests/acl/src/lib.rs b/core/tests/acl/src/lib.rs index 91119b95f76c..bf4d72adf112 100644 --- a/core/tests/acl/src/lib.rs +++ b/core/tests/acl/src/lib.rs @@ -1,3 +1,7 @@ +// Copyright 2019-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + #[cfg(test)] mod tests { use std::{ From 6435bff3b61b3d7dc76eab45c781306d6c59b78f Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 17 Jan 2024 12:59:58 -0300 Subject: [PATCH 48/69] fix on windows --- core/tauri-utils/src/acl/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/tauri-utils/src/acl/build.rs b/core/tauri-utils/src/acl/build.rs index 491f0e76445d..1a956f0fc80a 100644 --- a/core/tauri-utils/src/acl/build.rs +++ b/core/tauri-utils/src/acl/build.rs @@ -307,7 +307,7 @@ commands.deny = ["{command}"] "###, command = command, slugified_command = slugified_command, - schema_path = schema_path.display() + schema_path = schema_path.display().to_string().replace("\\", "\\\\") ); std::fs::write(path.join(format!("{command}.toml")), toml) From 96bc5c13f4fdb361629de30a8a01beb241475a97 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 17 Jan 2024 13:00:06 -0300 Subject: [PATCH 49/69] update global api --- core/tauri/scripts/bundle.global.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/tauri/scripts/bundle.global.js b/core/tauri/scripts/bundle.global.js index 3083bcdd81f1..a042236f150c 100644 --- a/core/tauri/scripts/bundle.global.js +++ b/core/tauri/scripts/bundle.global.js @@ -1 +1 @@ -var __TAURI_IIFE__=function(e){"use strict";function n(e,n,t,i){if("a"===t&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof n?e!==n||!i:!n.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===t?i:"a"===t?i.call(e):i?i.value:n.get(e)}function t(e,n,t,i,r){if("m"===i)throw new TypeError("Private method is not writable");if("a"===i&&!r)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof n?e!==n||!r:!n.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===i?r.call(e,t):r?r.value=t:n.set(e,t),t}var i,r;function a(e,n=!1){return window.__TAURI_INTERNALS__.transformCallback(e,n)}"function"==typeof SuppressedError&&SuppressedError;class s{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,i.set(this,(()=>{})),this.id=a((e=>{n(this,i,"f").call(this,e)}))}set onmessage(e){t(this,i,e,"f")}get onmessage(){return n(this,i,"f")}toJSON(){return`__CHANNEL__:${this.id}`}}i=new WeakMap;class l{constructor(e,n,t){this.plugin=e,this.event=n,this.channelId=t}async unregister(){return o(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}}async function o(e,n={},t){return window.__TAURI_INTERNALS__.invoke(e,n,t)}class u{get rid(){return n(this,r,"f")}constructor(e){r.set(this,void 0),t(this,r,e,"f")}async close(){return o("plugin:resources|close",{rid:this.rid})}}r=new WeakMap;var c=Object.freeze({__proto__:null,Channel:s,PluginListener:l,Resource:u,addPluginListener:async function(e,n,t){const i=new s;return i.onmessage=t,o(`plugin:${e}|register_listener`,{event:n,handler:i}).then((()=>new l(e,n,i.id)))},convertFileSrc:function(e,n="asset"){return window.__TAURI_INTERNALS__.convertFileSrc(e,n)},invoke:o,transformCallback:a});var d,p=Object.freeze({__proto__:null,getName:async function(){return o("plugin:app|name")},getTauriVersion:async function(){return o("plugin:app|tauri_version")},getVersion:async function(){return o("plugin:app|version")},hide:async function(){return o("plugin:app|app_hide")},show:async function(){return o("plugin:app|app_show")}});async function h(e,n){await o("plugin:event|unlisten",{event:e,eventId:n})}async function y(e,n,t){return o("plugin:event|listen",{event:e,windowLabel:t?.target,handler:a(n)}).then((n=>async()=>h(e,n)))}async function g(e,n,t){return y(e,(t=>{n(t),h(e,t.id).catch((()=>{}))}),t)}async function w(e,n,t){await o("plugin:event|emit",{event:e,windowLabel:t?.target,payload:n})}!function(e){e.WINDOW_RESIZED="tauri://resize",e.WINDOW_MOVED="tauri://move",e.WINDOW_CLOSE_REQUESTED="tauri://close-requested",e.WINDOW_CREATED="tauri://window-created",e.WINDOW_DESTROYED="tauri://destroyed",e.WINDOW_FOCUS="tauri://focus",e.WINDOW_BLUR="tauri://blur",e.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",e.WINDOW_THEME_CHANGED="tauri://theme-changed",e.WINDOW_FILE_DROP="tauri://file-drop",e.WINDOW_FILE_DROP_HOVER="tauri://file-drop-hover",e.WINDOW_FILE_DROP_CANCELLED="tauri://file-drop-cancelled"}(d||(d={}));var _=Object.freeze({__proto__:null,get TauriEvent(){return d},emit:w,listen:y,once:g});class m{constructor(e,n){this.type="Logical",this.width=e,this.height=n}}class b{constructor(e,n){this.type="Physical",this.width=e,this.height=n}toLogical(e){return new m(this.width/e,this.height/e)}}class f{constructor(e,n){this.type="Logical",this.x=e,this.y=n}}class v{constructor(e,n){this.type="Physical",this.x=e,this.y=n}toLogical(e){return new f(this.x/e,this.y/e)}}var k,D,A=Object.freeze({__proto__:null,LogicalPosition:f,LogicalSize:m,PhysicalPosition:v,PhysicalSize:b});!function(e){e[e.Critical=1]="Critical",e[e.Informational=2]="Informational"}(k||(k={}));class E{constructor(e){this._preventDefault=!1,this.event=e.event,this.windowLabel=e.windowLabel,this.id=e.id}preventDefault(){this._preventDefault=!0}isPreventDefault(){return this._preventDefault}}function I(){return new P(window.__TAURI_INTERNALS__.metadata.currentWindow.label,{skip:!0})}function L(){return window.__TAURI_INTERNALS__.metadata.windows.map((e=>new P(e.label,{skip:!0})))}!function(e){e.None="none",e.Normal="normal",e.Indeterminate="indeterminate",e.Paused="paused",e.Error="error"}(D||(D={}));const S=["tauri://created","tauri://error"];class P{constructor(e,n={}){this.label=e,this.listeners=Object.create(null),n?.skip||o("plugin:window|create",{options:{...n,label:e}}).then((async()=>this.emit("tauri://created"))).catch((async e=>this.emit("tauri://error",e)))}static getByLabel(e){return L().some((n=>n.label===e))?new P(e,{skip:!0}):null}static getCurrent(){return I()}static getAll(){return L()}static async getFocusedWindow(){for(const e of L())if(await e.isFocused())return e;return null}async listen(e,n){return this._handleTauriEvent(e,n)?Promise.resolve((()=>{const t=this.listeners[e];t.splice(t.indexOf(n),1)})):y(e,n,{target:this.label})}async once(e,n){return this._handleTauriEvent(e,n)?Promise.resolve((()=>{const t=this.listeners[e];t.splice(t.indexOf(n),1)})):g(e,n,{target:this.label})}async emit(e,n){if(S.includes(e)){for(const t of this.listeners[e]||[])t({event:e,id:-1,windowLabel:this.label,payload:n});return Promise.resolve()}return w(e,n,{target:this.label})}_handleTauriEvent(e,n){return!!S.includes(e)&&(e in this.listeners?this.listeners[e].push(n):this.listeners[e]=[n],!0)}async scaleFactor(){return o("plugin:window|scale_factor",{label:this.label})}async innerPosition(){return o("plugin:window|inner_position",{label:this.label}).then((({x:e,y:n})=>new v(e,n)))}async outerPosition(){return o("plugin:window|outer_position",{label:this.label}).then((({x:e,y:n})=>new v(e,n)))}async innerSize(){return o("plugin:window|inner_size",{label:this.label}).then((({width:e,height:n})=>new b(e,n)))}async outerSize(){return o("plugin:window|outer_size",{label:this.label}).then((({width:e,height:n})=>new b(e,n)))}async isFullscreen(){return o("plugin:window|is_fullscreen",{label:this.label})}async isMinimized(){return o("plugin:window|is_minimized",{label:this.label})}async isMaximized(){return o("plugin:window|is_maximized",{label:this.label})}async isFocused(){return o("plugin:window|is_focused",{label:this.label})}async isDecorated(){return o("plugin:window|is_decorated",{label:this.label})}async isResizable(){return o("plugin:window|is_resizable",{label:this.label})}async isMaximizable(){return o("plugin:window|is_maximizable",{label:this.label})}async isMinimizable(){return o("plugin:window|is_minimizable",{label:this.label})}async isClosable(){return o("plugin:window|is_closable",{label:this.label})}async isVisible(){return o("plugin:window|is_visible",{label:this.label})}async title(){return o("plugin:window|title",{label:this.label})}async theme(){return o("plugin:window|theme",{label:this.label})}async center(){return o("plugin:window|center",{label:this.label})}async requestUserAttention(e){let n=null;return e&&(n=e===k.Critical?{type:"Critical"}:{type:"Informational"}),o("plugin:window|request_user_attention",{label:this.label,value:n})}async setResizable(e){return o("plugin:window|set_resizable",{label:this.label,value:e})}async setMaximizable(e){return o("plugin:window|set_maximizable",{label:this.label,value:e})}async setMinimizable(e){return o("plugin:window|set_minimizable",{label:this.label,value:e})}async setClosable(e){return o("plugin:window|set_closable",{label:this.label,value:e})}async setTitle(e){return o("plugin:window|set_title",{label:this.label,value:e})}async maximize(){return o("plugin:window|maximize",{label:this.label})}async unmaximize(){return o("plugin:window|unmaximize",{label:this.label})}async toggleMaximize(){return o("plugin:window|toggle_maximize",{label:this.label})}async minimize(){return o("plugin:window|minimize",{label:this.label})}async unminimize(){return o("plugin:window|unminimize",{label:this.label})}async show(){return o("plugin:window|show",{label:this.label})}async hide(){return o("plugin:window|hide",{label:this.label})}async close(){return o("plugin:window|close",{label:this.label})}async setDecorations(e){return o("plugin:window|set_decorations",{label:this.label,value:e})}async setShadow(e){return o("plugin:window|set_shadow",{label:this.label,value:e})}async setEffects(e){return o("plugin:window|set_effects",{label:this.label,value:e})}async clearEffects(){return o("plugin:window|set_effects",{label:this.label,value:null})}async setAlwaysOnTop(e){return o("plugin:window|set_always_on_top",{label:this.label,value:e})}async setAlwaysOnBottom(e){return o("plugin:window|set_always_on_bottom",{label:this.label,value:e})}async setContentProtected(e){return o("plugin:window|set_content_protected",{label:this.label,value:e})}async setSize(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return o("plugin:window|set_size",{label:this.label,value:{type:e.type,data:{width:e.width,height:e.height}}})}async setMinSize(e){if(e&&"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return o("plugin:window|set_min_size",{label:this.label,value:e?{type:e.type,data:{width:e.width,height:e.height}}:null})}async setMaxSize(e){if(e&&"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return o("plugin:window|set_max_size",{label:this.label,value:e?{type:e.type,data:{width:e.width,height:e.height}}:null})}async setPosition(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");return o("plugin:window|set_position",{label:this.label,value:{type:e.type,data:{x:e.x,y:e.y}}})}async setFullscreen(e){return o("plugin:window|set_fullscreen",{label:this.label,value:e})}async setFocus(){return o("plugin:window|set_focus",{label:this.label})}async setIcon(e){return o("plugin:window|set_icon",{label:this.label,value:"string"==typeof e?e:Array.from(e)})}async setSkipTaskbar(e){return o("plugin:window|set_skip_taskbar",{label:this.label,value:e})}async setCursorGrab(e){return o("plugin:window|set_cursor_grab",{label:this.label,value:e})}async setCursorVisible(e){return o("plugin:window|set_cursor_visible",{label:this.label,value:e})}async setCursorIcon(e){return o("plugin:window|set_cursor_icon",{label:this.label,value:e})}async setCursorPosition(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");return o("plugin:window|set_cursor_position",{label:this.label,value:{type:e.type,data:{x:e.x,y:e.y}}})}async setIgnoreCursorEvents(e){return o("plugin:window|set_ignore_cursor_events",{label:this.label,value:e})}async startDragging(){return o("plugin:window|start_dragging",{label:this.label})}async setProgressBar(e){return o("plugin:window|set_progress_bar",{label:this.label,value:e})}async onResized(e){return this.listen(d.WINDOW_RESIZED,(n=>{n.payload=R(n.payload),e(n)}))}async onMoved(e){return this.listen(d.WINDOW_MOVED,(n=>{n.payload=F(n.payload),e(n)}))}async onCloseRequested(e){return this.listen(d.WINDOW_CLOSE_REQUESTED,(n=>{const t=new E(n);Promise.resolve(e(t)).then((()=>{if(!t.isPreventDefault())return this.close()}))}))}async onFocusChanged(e){const n=await this.listen(d.WINDOW_FOCUS,(n=>{e({...n,payload:!0})})),t=await this.listen(d.WINDOW_BLUR,(n=>{e({...n,payload:!1})}));return()=>{n(),t()}}async onScaleChanged(e){return this.listen(d.WINDOW_SCALE_FACTOR_CHANGED,e)}async onFileDropEvent(e){const n=await this.listen(d.WINDOW_FILE_DROP,(n=>{e({...n,payload:{type:"drop",paths:n.payload.paths,position:F(n.payload.position)}})})),t=await this.listen(d.WINDOW_FILE_DROP_HOVER,(n=>{e({...n,payload:{type:"hover",paths:n.payload.paths,position:F(n.payload.position)}})})),i=await this.listen(d.WINDOW_FILE_DROP_CANCELLED,(n=>{e({...n,payload:{type:"cancel"}})}));return()=>{n(),t(),i()}}async onThemeChanged(e){return this.listen(d.WINDOW_THEME_CHANGED,e)}}var C,T;function x(e){return null===e?null:{name:e.name,scaleFactor:e.scaleFactor,position:F(e.position),size:R(e.size)}}function F(e){return new v(e.x,e.y)}function R(e){return new b(e.width,e.height)}!function(e){e.AppearanceBased="appearanceBased",e.Light="light",e.Dark="dark",e.MediumLight="mediumLight",e.UltraDark="ultraDark",e.Titlebar="titlebar",e.Selection="selection",e.Menu="menu",e.Popover="popover",e.Sidebar="sidebar",e.HeaderView="headerView",e.Sheet="sheet",e.WindowBackground="windowBackground",e.HudWindow="hudWindow",e.FullScreenUI="fullScreenUI",e.Tooltip="tooltip",e.ContentBackground="contentBackground",e.UnderWindowBackground="underWindowBackground",e.UnderPageBackground="underPageBackground",e.Mica="mica",e.Blur="blur",e.Acrylic="acrylic",e.Tabbed="tabbed",e.TabbedDark="tabbedDark",e.TabbedLight="tabbedLight"}(C||(C={})),function(e){e.FollowsWindowActiveState="followsWindowActiveState",e.Active="active",e.Inactive="inactive"}(T||(T={}));var z,W=Object.freeze({__proto__:null,CloseRequestedEvent:E,get Effect(){return C},get EffectState(){return T},LogicalPosition:f,LogicalSize:m,PhysicalPosition:v,PhysicalSize:b,get ProgressBarStatus(){return D},get UserAttentionType(){return k},Window:P,availableMonitors:async function(){return o("plugin:window|available_monitors").then((e=>e.map(x)))},currentMonitor:async function(){return o("plugin:window|current_monitor").then(x)},getAll:L,getCurrent:I,primaryMonitor:async function(){return o("plugin:window|primary_monitor").then(x)}});!function(e){e[e.Audio=1]="Audio",e[e.Cache=2]="Cache",e[e.Config=3]="Config",e[e.Data=4]="Data",e[e.LocalData=5]="LocalData",e[e.Document=6]="Document",e[e.Download=7]="Download",e[e.Picture=8]="Picture",e[e.Public=9]="Public",e[e.Video=10]="Video",e[e.Resource=11]="Resource",e[e.Temp=12]="Temp",e[e.AppConfig=13]="AppConfig",e[e.AppData=14]="AppData",e[e.AppLocalData=15]="AppLocalData",e[e.AppCache=16]="AppCache",e[e.AppLog=17]="AppLog",e[e.Desktop=18]="Desktop",e[e.Executable=19]="Executable",e[e.Font=20]="Font",e[e.Home=21]="Home",e[e.Runtime=22]="Runtime",e[e.Template=23]="Template"}(z||(z={}));var N=Object.freeze({__proto__:null,get BaseDirectory(){return z},appCacheDir:async function(){return o("plugin:path|resolve_directory",{directory:z.AppCache})},appConfigDir:async function(){return o("plugin:path|resolve_directory",{directory:z.AppConfig})},appDataDir:async function(){return o("plugin:path|resolve_directory",{directory:z.AppData})},appLocalDataDir:async function(){return o("plugin:path|resolve_directory",{directory:z.AppLocalData})},appLogDir:async function(){return o("plugin:path|resolve_directory",{directory:z.AppLog})},audioDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Audio})},basename:async function(e,n){return o("plugin:path|basename",{path:e,ext:n})},cacheDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Cache})},configDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Config})},dataDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Data})},delimiter:function(){return window.__TAURI_INTERNALS__.plugins.path.delimiter},desktopDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Desktop})},dirname:async function(e){return o("plugin:path|dirname",{path:e})},documentDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Document})},downloadDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Download})},executableDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Executable})},extname:async function(e){return o("plugin:path|extname",{path:e})},fontDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Font})},homeDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Home})},isAbsolute:async function(e){return o("plugin:path|isAbsolute",{path:e})},join:async function(...e){return o("plugin:path|join",{paths:e})},localDataDir:async function(){return o("plugin:path|resolve_directory",{directory:z.LocalData})},normalize:async function(e){return o("plugin:path|normalize",{path:e})},pictureDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Picture})},publicDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Public})},resolve:async function(...e){return o("plugin:path|resolve",{paths:e})},resolveResource:async function(e){return o("plugin:path|resolve_directory",{directory:z.Resource,path:e})},resourceDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Resource})},runtimeDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Runtime})},sep:function(){return window.__TAURI_INTERNALS__.plugins.path.sep},tempDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Temp})},templateDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Template})},videoDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Video})}});class O extends u{constructor(e,n){super(e),this.id=n}static async new(e){e?.menu&&(e.menu=[e.menu.rid,e.menu.kind]),e?.icon&&(e.icon="string"==typeof e.icon?e.icon:Array.from(e.icon));const n=new s;return e?.action&&(n.onmessage=e.action,delete e.action),o("plugin:tray|new",{options:e??{},handler:n}).then((([e,n])=>new O(e,n)))}async setIcon(e){let n=null;return e&&(n="string"==typeof e?e:Array.from(e)),o("plugin:tray|set_icon",{rid:this.rid,icon:n})}async setMenu(e){return e&&(e=[e.rid,e.kind]),o("plugin:tray|set_menu",{rid:this.rid,menu:e})}async setTooltip(e){return o("plugin:tray|set_tooltip",{rid:this.rid,tooltip:e})}async setTitle(e){return o("plugin:tray|set_title",{rid:this.rid,title:e})}async setVisible(e){return o("plugin:tray|set_visible",{rid:this.rid,visible:e})}async setTempDirPath(e){return o("plugin:tray|set_temp_dir_path",{rid:this.rid,path:e})}async setIconAsTemplate(e){return o("plugin:tray|set_icon_as_template",{rid:this.rid,asTemplate:e})}async setMenuOnLeftClick(e){return o("plugin:tray|set_show_menu_on_left_click",{rid:this.rid,onLeft:e})}}var M,U,B,V=Object.freeze({__proto__:null,TrayIcon:O});function H(e){if("items"in e)e.items=e.items?.map((e=>"rid"in e?e:H(e)));else if("action"in e&&e.action){const n=new s;return n.onmessage=e.action,delete e.action,{...e,handler:n}}return e}async function G(e,n){const t=new s;let i=null;return n&&"object"==typeof n&&("action"in n&&n.action&&(t.onmessage=n.action,delete n.action),"items"in n&&n.items&&(i=n.items.map((e=>"rid"in e?[e.rid,e.kind]:H(e))))),o("plugin:menu|new",{kind:e,options:n?{...n,items:i}:void 0,handler:t})}class j extends u{get id(){return n(this,M,"f")}get kind(){return n(this,U,"f")}constructor(e,n,i){super(e),M.set(this,void 0),U.set(this,void 0),t(this,M,n,"f"),t(this,U,i,"f")}}M=new WeakMap,U=new WeakMap;class q extends j{constructor(e,n){super(e,n,"MenuItem")}static async new(e){return G("MenuItem",e).then((([e,n])=>new q(e,n)))}async text(){return o("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return o("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return o("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return o("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return o("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}}class Q extends j{constructor(e,n){super(e,n,"Check")}static async new(e){return G("Check",e).then((([e,n])=>new Q(e,n)))}async text(){return o("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return o("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return o("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return o("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return o("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}async isChecked(){return o("plugin:menu|is_checked",{rid:this.rid})}async setChecked(e){return o("plugin:menu|set_checked",{rid:this.rid,checked:e})}}!function(e){e.Add="Add",e.Advanced="Advanced",e.Bluetooth="Bluetooth",e.Bookmarks="Bookmarks",e.Caution="Caution",e.ColorPanel="ColorPanel",e.ColumnView="ColumnView",e.Computer="Computer",e.EnterFullScreen="EnterFullScreen",e.Everyone="Everyone",e.ExitFullScreen="ExitFullScreen",e.FlowView="FlowView",e.Folder="Folder",e.FolderBurnable="FolderBurnable",e.FolderSmart="FolderSmart",e.FollowLinkFreestanding="FollowLinkFreestanding",e.FontPanel="FontPanel",e.GoLeft="GoLeft",e.GoRight="GoRight",e.Home="Home",e.IChatTheater="IChatTheater",e.IconView="IconView",e.Info="Info",e.InvalidDataFreestanding="InvalidDataFreestanding",e.LeftFacingTriangle="LeftFacingTriangle",e.ListView="ListView",e.LockLocked="LockLocked",e.LockUnlocked="LockUnlocked",e.MenuMixedState="MenuMixedState",e.MenuOnState="MenuOnState",e.MobileMe="MobileMe",e.MultipleDocuments="MultipleDocuments",e.Network="Network",e.Path="Path",e.PreferencesGeneral="PreferencesGeneral",e.QuickLook="QuickLook",e.RefreshFreestanding="RefreshFreestanding",e.Refresh="Refresh",e.Remove="Remove",e.RevealFreestanding="RevealFreestanding",e.RightFacingTriangle="RightFacingTriangle",e.Share="Share",e.Slideshow="Slideshow",e.SmartBadge="SmartBadge",e.StatusAvailable="StatusAvailable",e.StatusNone="StatusNone",e.StatusPartiallyAvailable="StatusPartiallyAvailable",e.StatusUnavailable="StatusUnavailable",e.StopProgressFreestanding="StopProgressFreestanding",e.StopProgress="StopProgress",e.TrashEmpty="TrashEmpty",e.TrashFull="TrashFull",e.User="User",e.UserAccounts="UserAccounts",e.UserGroup="UserGroup",e.UserGuest="UserGuest"}(B||(B={}));class $ extends j{constructor(e,n){super(e,n,"Icon")}static async new(e){return G("Icon",e).then((([e,n])=>new $(e,n)))}async text(){return o("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return o("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return o("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return o("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return o("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}async setIcon(e){return o("plugin:menu|set_icon",{rid:this.rid,icon:e})}}class Z extends j{constructor(e,n){super(e,n,"Predefined")}static async new(e){return G("Predefined",e).then((([e,n])=>new Z(e,n)))}async text(){return o("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return o("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}}function J([e,n,t]){switch(t){case"Submenu":return new K(e,n);case"Predefined":return new Z(e,n);case"Check":return new Q(e,n);case"Icon":return new $(e,n);default:return new q(e,n)}}class K extends j{constructor(e,n){super(e,n,"Submenu")}static async new(e){return G("Submenu",e).then((([e,n])=>new K(e,n)))}async text(){return o("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return o("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return o("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return o("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async append(e){return o("plugin:menu|append",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async prepend(e){return o("plugin:menu|prepend",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async insert(e,n){return o("plugin:menu|insert",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e)),position:n})}async remove(e){return o("plugin:menu|remove",{rid:this.rid,kind:this.kind,item:[e.rid,e.kind]})}async removeAt(e){return o("plugin:menu|remove_at",{rid:this.rid,kind:this.kind,position:e}).then(J)}async items(){return o("plugin:menu|items",{rid:this.rid,kind:this.kind}).then((e=>e.map(J)))}async get(e){return o("plugin:menu|get",{rid:this.rid,kind:this.kind,id:e}).then((e=>e?J(e):null))}async popup(e,n){let t=null;return e&&(t={type:e instanceof v?"Physical":"Logical",data:e}),o("plugin:menu|popup",{rid:this.rid,kind:this.kind,window:n?.label??null,at:t})}async setAsWindowsMenuForNSApp(){return o("plugin:menu|set_as_windows_menu_for_nsapp",{rid:this.rid})}async setAsHelpMenuForNSApp(){return o("plugin:menu|set_as_help_menu_for_nsapp",{rid:this.rid})}}function Y([e,n,t]){switch(t){case"Submenu":return new K(e,n);case"Predefined":return new Z(e,n);case"Check":return new Q(e,n);case"Icon":return new $(e,n);default:return new q(e,n)}}class X extends j{constructor(e,n){super(e,n,"Menu")}static async new(e){return G("Menu",e).then((([e,n])=>new X(e,n)))}static async default(){return o("plugin:menu|default").then((([e,n])=>new X(e,n)))}async append(e){return o("plugin:menu|append",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async prepend(e){return o("plugin:menu|prepend",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async insert(e,n){return o("plugin:menu|insert",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e)),position:n})}async remove(e){return o("plugin:menu|remove",{rid:this.rid,kind:this.kind,item:[e.rid,e.kind]})}async removeAt(e){return o("plugin:menu|remove_at",{rid:this.rid,kind:this.kind,position:e}).then(Y)}async items(){return o("plugin:menu|items",{rid:this.rid,kind:this.kind}).then((e=>e.map(Y)))}async get(e){return o("plugin:menu|get",{rid:this.rid,kind:this.kind,id:e}).then((e=>e?Y(e):null))}async popup(e,n){let t=null;return e&&(t={type:e instanceof v?"Physical":"Logical",data:e}),o("plugin:menu|popup",{rid:this.rid,kind:this.kind,window:n?.label??null,at:t})}async setAsAppMenu(){return o("plugin:menu|set_as_app_menu",{rid:this.rid}).then((e=>e?new X(e[0],e[1]):null))}async setAsWindowMenu(e){return o("plugin:menu|set_as_window_menu",{rid:this.rid,window:e?.label??null}).then((e=>e?new X(e[0],e[1]):null))}}var ee=Object.freeze({__proto__:null,CheckMenuItem:Q,IconMenuItem:$,Menu:X,MenuItem:q,get NativeIcon(){return B},PredefinedMenuItem:Z,Submenu:K});return e.app=p,e.core=c,e.dpi=A,e.event=_,e.menu=ee,e.path=N,e.tray=V,e.window=W,e}({});window.__TAURI__=__TAURI_IIFE__; +var __TAURI_IIFE__=function(e){"use strict";function n(e,n,t,i){if("a"===t&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof n?e!==n||!i:!n.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===t?i:"a"===t?i.call(e):i?i.value:n.get(e)}function t(e,n,t,i,r){if("m"===i)throw new TypeError("Private method is not writable");if("a"===i&&!r)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof n?e!==n||!r:!n.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===i?r.call(e,t):r?r.value=t:n.set(e,t),t}var i,r;function a(e,n=!1){return window.__TAURI_INTERNALS__.transformCallback(e,n)}"function"==typeof SuppressedError&&SuppressedError;class s{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,i.set(this,(()=>{})),this.id=a((e=>{n(this,i,"f").call(this,e)}))}set onmessage(e){t(this,i,e,"f")}get onmessage(){return n(this,i,"f")}toJSON(){return`__CHANNEL__:${this.id}`}}i=new WeakMap;class l{constructor(e,n,t){this.plugin=e,this.event=n,this.channelId=t}async unregister(){return o(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}}async function o(e,n={},t){return window.__TAURI_INTERNALS__.invoke(e,n,t)}class u{get rid(){return n(this,r,"f")}constructor(e){r.set(this,void 0),t(this,r,e,"f")}async close(){return o("plugin:resources|close",{rid:this.rid})}}r=new WeakMap;var c=Object.freeze({__proto__:null,Channel:s,PluginListener:l,Resource:u,addPluginListener:async function(e,n,t){const i=new s;return i.onmessage=t,o(`plugin:${e}|register_listener`,{event:n,handler:i}).then((()=>new l(e,n,i.id)))},convertFileSrc:function(e,n="asset"){return window.__TAURI_INTERNALS__.convertFileSrc(e,n)},invoke:o,transformCallback:a});var d,p=Object.freeze({__proto__:null,getName:async function(){return o("plugin:app|name")},getTauriVersion:async function(){return o("plugin:app|tauri_version")},getVersion:async function(){return o("plugin:app|version")},hide:async function(){return o("plugin:app|app_hide")},show:async function(){return o("plugin:app|app_show")}});async function h(e,n){await o("plugin:event|unlisten",{event:e,eventId:n})}async function y(e,n,t){return o("plugin:event|listen",{event:e,windowLabel:t?.target,handler:a(n)}).then((n=>async()=>h(e,n)))}async function g(e,n,t){return y(e,(t=>{n(t),h(e,t.id).catch((()=>{}))}),t)}async function w(e,n,t){await o("plugin:event|emit",{event:e,windowLabel:t?.target,payload:n})}!function(e){e.WINDOW_RESIZED="tauri://resize",e.WINDOW_MOVED="tauri://move",e.WINDOW_CLOSE_REQUESTED="tauri://close-requested",e.WINDOW_CREATED="tauri://window-created",e.WINDOW_DESTROYED="tauri://destroyed",e.WINDOW_FOCUS="tauri://focus",e.WINDOW_BLUR="tauri://blur",e.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",e.WINDOW_THEME_CHANGED="tauri://theme-changed",e.WINDOW_FILE_DROP="tauri://file-drop",e.WINDOW_FILE_DROP_HOVER="tauri://file-drop-hover",e.WINDOW_FILE_DROP_CANCELLED="tauri://file-drop-cancelled"}(d||(d={}));var _=Object.freeze({__proto__:null,get TauriEvent(){return d},emit:w,listen:y,once:g});class m{constructor(e,n){this.type="Logical",this.width=e,this.height=n}}class b{constructor(e,n){this.type="Physical",this.width=e,this.height=n}toLogical(e){return new m(this.width/e,this.height/e)}}class f{constructor(e,n){this.type="Logical",this.x=e,this.y=n}}class v{constructor(e,n){this.type="Physical",this.x=e,this.y=n}toLogical(e){return new f(this.x/e,this.y/e)}}var k,D,A=Object.freeze({__proto__:null,LogicalPosition:f,LogicalSize:m,PhysicalPosition:v,PhysicalSize:b});!function(e){e[e.Critical=1]="Critical",e[e.Informational=2]="Informational"}(k||(k={}));class E{constructor(e){this._preventDefault=!1,this.event=e.event,this.windowLabel=e.windowLabel,this.id=e.id}preventDefault(){this._preventDefault=!0}isPreventDefault(){return this._preventDefault}}function I(){return new P(window.__TAURI_INTERNALS__.metadata.currentWindow.label,{skip:!0})}function L(){return window.__TAURI_INTERNALS__.metadata.windows.map((e=>new P(e.label,{skip:!0})))}!function(e){e.None="none",e.Normal="normal",e.Indeterminate="indeterminate",e.Paused="paused",e.Error="error"}(D||(D={}));const S=["tauri://created","tauri://error"];class P{constructor(e,n={}){this.label=e,this.listeners=Object.create(null),n?.skip||o("plugin:window|create",{options:{...n,label:e}}).then((async()=>this.emit("tauri://created"))).catch((async e=>this.emit("tauri://error",e)))}static getByLabel(e){return L().some((n=>n.label===e))?new P(e,{skip:!0}):null}static getCurrent(){return I()}static getAll(){return L()}static async getFocusedWindow(){for(const e of L())if(await e.isFocused())return e;return null}async listen(e,n){return this._handleTauriEvent(e,n)?Promise.resolve((()=>{const t=this.listeners[e];t.splice(t.indexOf(n),1)})):y(e,n,{target:this.label})}async once(e,n){return this._handleTauriEvent(e,n)?Promise.resolve((()=>{const t=this.listeners[e];t.splice(t.indexOf(n),1)})):g(e,n,{target:this.label})}async emit(e,n){if(S.includes(e)){for(const t of this.listeners[e]||[])t({event:e,id:-1,windowLabel:this.label,payload:n});return Promise.resolve()}return w(e,n,{target:this.label})}_handleTauriEvent(e,n){return!!S.includes(e)&&(e in this.listeners?this.listeners[e].push(n):this.listeners[e]=[n],!0)}async scaleFactor(){return o("plugin:window|scale_factor",{label:this.label})}async innerPosition(){return o("plugin:window|inner_position",{label:this.label}).then((({x:e,y:n})=>new v(e,n)))}async outerPosition(){return o("plugin:window|outer_position",{label:this.label}).then((({x:e,y:n})=>new v(e,n)))}async innerSize(){return o("plugin:window|inner_size",{label:this.label}).then((({width:e,height:n})=>new b(e,n)))}async outerSize(){return o("plugin:window|outer_size",{label:this.label}).then((({width:e,height:n})=>new b(e,n)))}async isFullscreen(){return o("plugin:window|is_fullscreen",{label:this.label})}async isMinimized(){return o("plugin:window|is_minimized",{label:this.label})}async isMaximized(){return o("plugin:window|is_maximized",{label:this.label})}async isFocused(){return o("plugin:window|is_focused",{label:this.label})}async isDecorated(){return o("plugin:window|is_decorated",{label:this.label})}async isResizable(){return o("plugin:window|is_resizable",{label:this.label})}async isMaximizable(){return o("plugin:window|is_maximizable",{label:this.label})}async isMinimizable(){return o("plugin:window|is_minimizable",{label:this.label})}async isClosable(){return o("plugin:window|is_closable",{label:this.label})}async isVisible(){return o("plugin:window|is_visible",{label:this.label})}async title(){return o("plugin:window|title",{label:this.label})}async theme(){return o("plugin:window|theme",{label:this.label})}async center(){return o("plugin:window|center",{label:this.label})}async requestUserAttention(e){let n=null;return e&&(n=e===k.Critical?{type:"Critical"}:{type:"Informational"}),o("plugin:window|request_user_attention",{label:this.label,value:n})}async setResizable(e){return o("plugin:window|set_resizable",{label:this.label,value:e})}async setMaximizable(e){return o("plugin:window|set_maximizable",{label:this.label,value:e})}async setMinimizable(e){return o("plugin:window|set_minimizable",{label:this.label,value:e})}async setClosable(e){return o("plugin:window|set_closable",{label:this.label,value:e})}async setTitle(e){return o("plugin:window|set_title",{label:this.label,value:e})}async maximize(){return o("plugin:window|maximize",{label:this.label})}async unmaximize(){return o("plugin:window|unmaximize",{label:this.label})}async toggleMaximize(){return o("plugin:window|toggle_maximize",{label:this.label})}async minimize(){return o("plugin:window|minimize",{label:this.label})}async unminimize(){return o("plugin:window|unminimize",{label:this.label})}async show(){return o("plugin:window|show",{label:this.label})}async hide(){return o("plugin:window|hide",{label:this.label})}async close(){return o("plugin:window|close",{label:this.label})}async setDecorations(e){return o("plugin:window|set_decorations",{label:this.label,value:e})}async setShadow(e){return o("plugin:window|set_shadow",{label:this.label,value:e})}async setEffects(e){return o("plugin:window|set_effects",{label:this.label,value:e})}async clearEffects(){return o("plugin:window|set_effects",{label:this.label,value:null})}async setAlwaysOnTop(e){return o("plugin:window|set_always_on_top",{label:this.label,value:e})}async setAlwaysOnBottom(e){return o("plugin:window|set_always_on_bottom",{label:this.label,value:e})}async setContentProtected(e){return o("plugin:window|set_content_protected",{label:this.label,value:e})}async setSize(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return o("plugin:window|set_size",{label:this.label,value:{type:e.type,data:{width:e.width,height:e.height}}})}async setMinSize(e){if(e&&"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return o("plugin:window|set_min_size",{label:this.label,value:e?{type:e.type,data:{width:e.width,height:e.height}}:null})}async setMaxSize(e){if(e&&"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return o("plugin:window|set_max_size",{label:this.label,value:e?{type:e.type,data:{width:e.width,height:e.height}}:null})}async setPosition(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");return o("plugin:window|set_position",{label:this.label,value:{type:e.type,data:{x:e.x,y:e.y}}})}async setFullscreen(e){return o("plugin:window|set_fullscreen",{label:this.label,value:e})}async setFocus(){return o("plugin:window|set_focus",{label:this.label})}async setIcon(e){return o("plugin:window|set_icon",{label:this.label,value:"string"==typeof e?e:Array.from(e)})}async setSkipTaskbar(e){return o("plugin:window|set_skip_taskbar",{label:this.label,value:e})}async setCursorGrab(e){return o("plugin:window|set_cursor_grab",{label:this.label,value:e})}async setCursorVisible(e){return o("plugin:window|set_cursor_visible",{label:this.label,value:e})}async setCursorIcon(e){return o("plugin:window|set_cursor_icon",{label:this.label,value:e})}async setCursorPosition(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");return o("plugin:window|set_cursor_position",{label:this.label,value:{type:e.type,data:{x:e.x,y:e.y}}})}async setIgnoreCursorEvents(e){return o("plugin:window|set_ignore_cursor_events",{label:this.label,value:e})}async startDragging(){return o("plugin:window|start_dragging",{label:this.label})}async setProgressBar(e){return o("plugin:window|set_progress_bar",{label:this.label,value:e})}async onResized(e){return this.listen(d.WINDOW_RESIZED,(n=>{n.payload=R(n.payload),e(n)}))}async onMoved(e){return this.listen(d.WINDOW_MOVED,(n=>{n.payload=F(n.payload),e(n)}))}async onCloseRequested(e){return this.listen(d.WINDOW_CLOSE_REQUESTED,(n=>{const t=new E(n);Promise.resolve(e(t)).then((()=>{if(!t.isPreventDefault())return this.close()}))}))}async onFocusChanged(e){const n=await this.listen(d.WINDOW_FOCUS,(n=>{e({...n,payload:!0})})),t=await this.listen(d.WINDOW_BLUR,(n=>{e({...n,payload:!1})}));return()=>{n(),t()}}async onScaleChanged(e){return this.listen(d.WINDOW_SCALE_FACTOR_CHANGED,e)}async onFileDropEvent(e){const n=await this.listen(d.WINDOW_FILE_DROP,(n=>{e({...n,payload:{type:"drop",paths:n.payload.paths,position:F(n.payload.position)}})})),t=await this.listen(d.WINDOW_FILE_DROP_HOVER,(n=>{e({...n,payload:{type:"hover",paths:n.payload.paths,position:F(n.payload.position)}})})),i=await this.listen(d.WINDOW_FILE_DROP_CANCELLED,(n=>{e({...n,payload:{type:"cancel"}})}));return()=>{n(),t(),i()}}async onThemeChanged(e){return this.listen(d.WINDOW_THEME_CHANGED,e)}}var C,T;function x(e){return null===e?null:{name:e.name,scaleFactor:e.scaleFactor,position:F(e.position),size:R(e.size)}}function F(e){return new v(e.x,e.y)}function R(e){return new b(e.width,e.height)}!function(e){e.AppearanceBased="appearanceBased",e.Light="light",e.Dark="dark",e.MediumLight="mediumLight",e.UltraDark="ultraDark",e.Titlebar="titlebar",e.Selection="selection",e.Menu="menu",e.Popover="popover",e.Sidebar="sidebar",e.HeaderView="headerView",e.Sheet="sheet",e.WindowBackground="windowBackground",e.HudWindow="hudWindow",e.FullScreenUI="fullScreenUI",e.Tooltip="tooltip",e.ContentBackground="contentBackground",e.UnderWindowBackground="underWindowBackground",e.UnderPageBackground="underPageBackground",e.Mica="mica",e.Blur="blur",e.Acrylic="acrylic",e.Tabbed="tabbed",e.TabbedDark="tabbedDark",e.TabbedLight="tabbedLight"}(C||(C={})),function(e){e.FollowsWindowActiveState="followsWindowActiveState",e.Active="active",e.Inactive="inactive"}(T||(T={}));var z,W=Object.freeze({__proto__:null,CloseRequestedEvent:E,get Effect(){return C},get EffectState(){return T},LogicalPosition:f,LogicalSize:m,PhysicalPosition:v,PhysicalSize:b,get ProgressBarStatus(){return D},get UserAttentionType(){return k},Window:P,availableMonitors:async function(){return o("plugin:window|available_monitors").then((e=>e.map(x)))},currentMonitor:async function(){return o("plugin:window|current_monitor").then(x)},getAll:L,getCurrent:I,primaryMonitor:async function(){return o("plugin:window|primary_monitor").then(x)}});!function(e){e[e.Audio=1]="Audio",e[e.Cache=2]="Cache",e[e.Config=3]="Config",e[e.Data=4]="Data",e[e.LocalData=5]="LocalData",e[e.Document=6]="Document",e[e.Download=7]="Download",e[e.Picture=8]="Picture",e[e.Public=9]="Public",e[e.Video=10]="Video",e[e.Resource=11]="Resource",e[e.Temp=12]="Temp",e[e.AppConfig=13]="AppConfig",e[e.AppData=14]="AppData",e[e.AppLocalData=15]="AppLocalData",e[e.AppCache=16]="AppCache",e[e.AppLog=17]="AppLog",e[e.Desktop=18]="Desktop",e[e.Executable=19]="Executable",e[e.Font=20]="Font",e[e.Home=21]="Home",e[e.Runtime=22]="Runtime",e[e.Template=23]="Template"}(z||(z={}));var N=Object.freeze({__proto__:null,get BaseDirectory(){return z},appCacheDir:async function(){return o("plugin:path|resolve_directory",{directory:z.AppCache})},appConfigDir:async function(){return o("plugin:path|resolve_directory",{directory:z.AppConfig})},appDataDir:async function(){return o("plugin:path|resolve_directory",{directory:z.AppData})},appLocalDataDir:async function(){return o("plugin:path|resolve_directory",{directory:z.AppLocalData})},appLogDir:async function(){return o("plugin:path|resolve_directory",{directory:z.AppLog})},audioDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Audio})},basename:async function(e,n){return o("plugin:path|basename",{path:e,ext:n})},cacheDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Cache})},configDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Config})},dataDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Data})},delimiter:function(){return window.__TAURI_INTERNALS__.plugins.path.delimiter},desktopDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Desktop})},dirname:async function(e){return o("plugin:path|dirname",{path:e})},documentDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Document})},downloadDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Download})},executableDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Executable})},extname:async function(e){return o("plugin:path|extname",{path:e})},fontDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Font})},homeDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Home})},isAbsolute:async function(e){return o("plugin:path|isAbsolute",{path:e})},join:async function(...e){return o("plugin:path|join",{paths:e})},localDataDir:async function(){return o("plugin:path|resolve_directory",{directory:z.LocalData})},normalize:async function(e){return o("plugin:path|normalize",{path:e})},pictureDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Picture})},publicDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Public})},resolve:async function(...e){return o("plugin:path|resolve",{paths:e})},resolveResource:async function(e){return o("plugin:path|resolve_directory",{directory:z.Resource,path:e})},resourceDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Resource})},runtimeDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Runtime})},sep:function(){return window.__TAURI_INTERNALS__.plugins.path.sep},tempDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Temp})},templateDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Template})},videoDir:async function(){return o("plugin:path|resolve_directory",{directory:z.Video})}});class O extends u{constructor(e,n){super(e),this.id=n}static async new(e){e?.menu&&(e.menu=[e.menu.rid,e.menu.kind]),e?.icon&&(e.icon="string"==typeof e.icon?e.icon:Array.from(e.icon));const n=new s;return e?.action&&(n.onmessage=e.action,delete e.action),o("plugin:tray|new",{options:e??{},handler:n}).then((([e,n])=>new O(e,n)))}async setIcon(e){let n=null;return e&&(n="string"==typeof e?e:Array.from(e)),o("plugin:tray|set_icon",{rid:this.rid,icon:n})}async setMenu(e){return e&&(e=[e.rid,e.kind]),o("plugin:tray|set_menu",{rid:this.rid,menu:e})}async setTooltip(e){return o("plugin:tray|set_tooltip",{rid:this.rid,tooltip:e})}async setTitle(e){return o("plugin:tray|set_title",{rid:this.rid,title:e})}async setVisible(e){return o("plugin:tray|set_visible",{rid:this.rid,visible:e})}async setTempDirPath(e){return o("plugin:tray|set_temp_dir_path",{rid:this.rid,path:e})}async setIconAsTemplate(e){return o("plugin:tray|set_icon_as_template",{rid:this.rid,asTemplate:e})}async setMenuOnLeftClick(e){return o("plugin:tray|set_show_menu_on_left_click",{rid:this.rid,onLeft:e})}}var M,U,B,V=Object.freeze({__proto__:null,TrayIcon:O});function H(e){if("items"in e)e.items=e.items?.map((e=>"rid"in e?e:H(e)));else if("action"in e&&e.action){const n=new s;return n.onmessage=e.action,delete e.action,{...e,handler:n}}return e}async function G(e,n){const t=new s;let i=null;return n&&"object"==typeof n&&("action"in n&&n.action&&(t.onmessage=n.action,delete n.action),"items"in n&&n.items&&(i=n.items.map((e=>"rid"in e?[e.rid,e.kind]:H(e))))),o("plugin:menu|new",{kind:e,options:n?{...n,items:i}:void 0,handler:t})}class j extends u{get id(){return n(this,M,"f")}get kind(){return n(this,U,"f")}constructor(e,n,i){super(e),M.set(this,void 0),U.set(this,void 0),t(this,M,n,"f"),t(this,U,i,"f")}}M=new WeakMap,U=new WeakMap;class q extends j{constructor(e,n){super(e,n,"MenuItem")}static async new(e){return G("MenuItem",e).then((([e,n])=>new q(e,n)))}async text(){return o("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return o("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return o("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return o("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return o("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}}class Q extends j{constructor(e,n){super(e,n,"Check")}static async new(e){return G("Check",e).then((([e,n])=>new Q(e,n)))}async text(){return o("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return o("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return o("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return o("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return o("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}async isChecked(){return o("plugin:menu|is_checked",{rid:this.rid})}async setChecked(e){return o("plugin:menu|set_checked",{rid:this.rid,checked:e})}}!function(e){e.Add="Add",e.Advanced="Advanced",e.Bluetooth="Bluetooth",e.Bookmarks="Bookmarks",e.Caution="Caution",e.ColorPanel="ColorPanel",e.ColumnView="ColumnView",e.Computer="Computer",e.EnterFullScreen="EnterFullScreen",e.Everyone="Everyone",e.ExitFullScreen="ExitFullScreen",e.FlowView="FlowView",e.Folder="Folder",e.FolderBurnable="FolderBurnable",e.FolderSmart="FolderSmart",e.FollowLinkFreestanding="FollowLinkFreestanding",e.FontPanel="FontPanel",e.GoLeft="GoLeft",e.GoRight="GoRight",e.Home="Home",e.IChatTheater="IChatTheater",e.IconView="IconView",e.Info="Info",e.InvalidDataFreestanding="InvalidDataFreestanding",e.LeftFacingTriangle="LeftFacingTriangle",e.ListView="ListView",e.LockLocked="LockLocked",e.LockUnlocked="LockUnlocked",e.MenuMixedState="MenuMixedState",e.MenuOnState="MenuOnState",e.MobileMe="MobileMe",e.MultipleDocuments="MultipleDocuments",e.Network="Network",e.Path="Path",e.PreferencesGeneral="PreferencesGeneral",e.QuickLook="QuickLook",e.RefreshFreestanding="RefreshFreestanding",e.Refresh="Refresh",e.Remove="Remove",e.RevealFreestanding="RevealFreestanding",e.RightFacingTriangle="RightFacingTriangle",e.Share="Share",e.Slideshow="Slideshow",e.SmartBadge="SmartBadge",e.StatusAvailable="StatusAvailable",e.StatusNone="StatusNone",e.StatusPartiallyAvailable="StatusPartiallyAvailable",e.StatusUnavailable="StatusUnavailable",e.StopProgressFreestanding="StopProgressFreestanding",e.StopProgress="StopProgress",e.TrashEmpty="TrashEmpty",e.TrashFull="TrashFull",e.User="User",e.UserAccounts="UserAccounts",e.UserGroup="UserGroup",e.UserGuest="UserGuest"}(B||(B={}));class $ extends j{constructor(e,n){super(e,n,"Icon")}static async new(e){return G("Icon",e).then((([e,n])=>new $(e,n)))}async text(){return o("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return o("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return o("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return o("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return o("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}async setIcon(e){return o("plugin:menu|set_icon",{rid:this.rid,icon:e})}}class Z extends j{constructor(e,n){super(e,n,"Predefined")}static async new(e){return G("Predefined",e).then((([e,n])=>new Z(e,n)))}async text(){return o("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return o("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}}function J([e,n,t]){switch(t){case"Submenu":return new K(e,n);case"Predefined":return new Z(e,n);case"Check":return new Q(e,n);case"Icon":return new $(e,n);default:return new q(e,n)}}class K extends j{constructor(e,n){super(e,n,"Submenu")}static async new(e){return G("Submenu",e).then((([e,n])=>new K(e,n)))}async text(){return o("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return o("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return o("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return o("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async append(e){return o("plugin:menu|append",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async prepend(e){return o("plugin:menu|prepend",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async insert(e,n){return o("plugin:menu|insert",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e)),position:n})}async remove(e){return o("plugin:menu|remove",{rid:this.rid,kind:this.kind,item:[e.rid,e.kind]})}async removeAt(e){return o("plugin:menu|remove_at",{rid:this.rid,kind:this.kind,position:e}).then(J)}async items(){return o("plugin:menu|items",{rid:this.rid,kind:this.kind}).then((e=>e.map(J)))}async get(e){return o("plugin:menu|get",{rid:this.rid,kind:this.kind,id:e}).then((e=>e?J(e):null))}async popup(e,n){let t=null;return e&&(t={type:e instanceof v?"Physical":"Logical",data:e}),o("plugin:menu|popup",{rid:this.rid,kind:this.kind,window:n?.label??null,at:t})}async setAsWindowsMenuForNSApp(){return o("plugin:menu|set_as_windows_menu_for_nsapp",{rid:this.rid})}async setAsHelpMenuForNSApp(){return o("plugin:menu|set_as_help_menu_for_nsapp",{rid:this.rid})}}function Y([e,n,t]){switch(t){case"Submenu":return new K(e,n);case"Predefined":return new Z(e,n);case"Check":return new Q(e,n);case"Icon":return new $(e,n);default:return new q(e,n)}}class X extends j{constructor(e,n){super(e,n,"Menu")}static async new(e){return G("Menu",e).then((([e,n])=>new X(e,n)))}static async default(){return o("plugin:menu|create_default").then((([e,n])=>new X(e,n)))}async append(e){return o("plugin:menu|append",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async prepend(e){return o("plugin:menu|prepend",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async insert(e,n){return o("plugin:menu|insert",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e)),position:n})}async remove(e){return o("plugin:menu|remove",{rid:this.rid,kind:this.kind,item:[e.rid,e.kind]})}async removeAt(e){return o("plugin:menu|remove_at",{rid:this.rid,kind:this.kind,position:e}).then(Y)}async items(){return o("plugin:menu|items",{rid:this.rid,kind:this.kind}).then((e=>e.map(Y)))}async get(e){return o("plugin:menu|get",{rid:this.rid,kind:this.kind,id:e}).then((e=>e?Y(e):null))}async popup(e,n){let t=null;return e&&(t={type:e instanceof v?"Physical":"Logical",data:e}),o("plugin:menu|popup",{rid:this.rid,kind:this.kind,window:n?.label??null,at:t})}async setAsAppMenu(){return o("plugin:menu|set_as_app_menu",{rid:this.rid}).then((e=>e?new X(e[0],e[1]):null))}async setAsWindowMenu(e){return o("plugin:menu|set_as_window_menu",{rid:this.rid,window:e?.label??null}).then((e=>e?new X(e[0],e[1]):null))}}var ee=Object.freeze({__proto__:null,CheckMenuItem:Q,IconMenuItem:$,Menu:X,MenuItem:q,get NativeIcon(){return B},PredefinedMenuItem:Z,Submenu:K});return e.app=p,e.core=c,e.dpi=A,e.event=_,e.menu=ee,e.path=N,e.tray=V,e.window=W,e}({});window.__TAURI__=__TAURI_IIFE__; From c194b2e5bd4a0c5aab78535ee830327df12ed146 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 17 Jan 2024 13:01:02 -0300 Subject: [PATCH 50/69] glob is no longer optional on tauri-utils --- core/tauri-utils/Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/tauri-utils/Cargo.toml b/core/tauri-utils/Cargo.toml index 701c2c63ddf2..108423ce5eb8 100644 --- a/core/tauri-utils/Cargo.toml +++ b/core/tauri-utils/Cargo.toml @@ -32,7 +32,7 @@ ctor = "0.2" json5 = { version = "0.4", optional = true } toml = { version = "0.8", features = ["parse"] } json-patch = "1.2" -glob = { version = "0.3", optional = true } +glob = "0.3" walkdir = { version = "2", optional = true } memchr = "2" semver = "1" @@ -45,11 +45,11 @@ cargo_metadata = { version = "0.18", optional = true } heck = "0.4" [features] -build = [ "proc-macro2", "quote", "cargo_metadata", "glob", "schema" ] +build = [ "proc-macro2", "quote", "cargo_metadata", "schema" ] compression = [ "brotli" ] schema = [ "schemars" ] isolation = [ "aes-gcm", "getrandom", "serialize-to-javascript" ] process-relaunch-dangerous-allow-symlink-macos = [ ] config-json5 = [ "json5" ] config-toml = [] -resources = [ "glob", "walkdir" ] +resources = [ "walkdir" ] From 5231a9e2ff0914a37f5bce25bd6aea27eb8673f6 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 17 Jan 2024 14:10:32 -0300 Subject: [PATCH 51/69] add missing permissions on api example [skip ci] --- .../api/src-tauri/capabilities/run-app.toml | 77 ++++++++++++++++++- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/examples/api/src-tauri/capabilities/run-app.toml b/examples/api/src-tauri/capabilities/run-app.toml index a392dcb54a18..a4fd8c4fd368 100644 --- a/examples/api/src-tauri/capabilities/run-app.toml +++ b/examples/api/src-tauri/capabilities/run-app.toml @@ -10,6 +10,79 @@ permissions = [ "resources:default", "menu:default", "tray:default", - "sample:allow-ping-scoped", - "sample:global-scope", + # app + "app:allow-app-hide", + "app:allow-app-show", + # window + "window:allow-create", + "window:allow-center", + "window:allow-request-user-attention", + "window:allow-set-resizable", + "window:allow-set-maximizable", + "window:allow-set-minimizable", + "window:allow-set-closable", + "window:allow-set-title", + "window:allow-maximize", + "window:allow-unmaximize", + "window:allow-minimize", + "window:allow-unminimize", + "window:allow-show", + "window:allow-hide", + "window:allow-close", + "window:allow-set-decorations", + "window:allow-set-shadow", + "window:allow-set-effects", + "window:allow-set-always-on-top", + "window:allow-set-always-on-bottom", + "window:allow-set-content-protected", + "window:allow-set-size", + "window:allow-set-min-size", + "window:allow-set-max-size", + "window:allow-set-position", + "window:allow-set-fullscreen", + "window:allow-set-focus", + "window:allow-set-skip-taskbar", + "window:allow-set-cursor-grab", + "window:allow-set-cursor-visible", + "window:allow-set-cursor-icon", + "window:allow-set-cursor-position", + "window:allow-set-ignore-cursor-events", + "window:allow-start-dragging", + "window:allow-set-progress-bar", + "window:allow-print", + "window:allow-set-icon", + "window:allow-toggle-maximize", + # menu + "menu:allow-new", + "menu:allow-append", + "menu:allow-prepend", + "menu:allow-insert", + "menu:allow-remove", + "menu:allow-remove-at", + "menu:allow-items", + "menu:allow-get", + "menu:allow-popup", + "menu:allow-create-default", + "menu:allow-set-as-app-menu", + "menu:allow-set-as-window-menu", + "menu:allow-text", + "menu:allow-set-text", + "menu:allow-is-enabled", + "menu:allow-set-enabled", + "menu:allow-set-accelerator", + "menu:allow-set-as-windows-menu-for-nsapp", + "menu:allow-set-as-help-menu-for-nsapp", + "menu:allow-is-checked", + "menu:allow-set-checked", + "menu:allow-set-icon", + # tray + "tray:allow-new", + "tray:allow-set-icon", + "tray:allow-set-menu", + "tray:allow-set-tooltip", + "tray:allow-set-title", + "tray:allow-set-visible", + "tray:allow-set-temp-dir-path", + "tray:allow-set-icon-as-template", + "tray:allow-set-show-menu-on-left-click", ] From 24bcb31705084285af74b788b5957ef81ae5a560 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 17 Jan 2024 15:13:23 -0300 Subject: [PATCH 52/69] remove ipc scope and dangerous remote access config --- core/tauri-config-schema/schema.json | 47 --- core/tauri-utils/src/config.rs | 18 -- core/tauri/src/app.rs | 2 - core/tauri/src/lib.rs | 5 - core/tauri/src/scope/ipc.rs | 423 --------------------------- core/tauri/src/scope/mod.rs | 3 - core/tauri/src/window/mod.rs | 46 +-- tooling/cli/schema.json | 47 --- 8 files changed, 1 insertion(+), 590 deletions(-) delete mode 100644 core/tauri/src/scope/ipc.rs diff --git a/core/tauri-config-schema/schema.json b/core/tauri-config-schema/schema.json index ddc1fff4291c..aa64fe31f97b 100644 --- a/core/tauri-config-schema/schema.json +++ b/core/tauri-config-schema/schema.json @@ -96,7 +96,6 @@ "scope": [] }, "dangerousDisableAssetCspModification": false, - "dangerousRemoteDomainIpcAccess": [], "freezePrototype": false }, "windows": [] @@ -254,7 +253,6 @@ "scope": [] }, "dangerousDisableAssetCspModification": false, - "dangerousRemoteDomainIpcAccess": [], "freezePrototype": false }, "allOf": [ @@ -2227,14 +2225,6 @@ } ] }, - "dangerousRemoteDomainIpcAccess": { - "description": "Allow external domains to send command to Tauri.\n\nBy default, external domains do not have access to `window.__TAURI__`, which means they cannot communicate with the commands defined in Rust. This prevents attacks where an externally loaded malicious or compromised sites could start executing commands on the user's device.\n\nThis configuration allows a set of external domains to have access to the Tauri commands. When you configure a domain to be allowed to access the IPC, all subpaths are allowed. Subdomains are not allowed.\n\n**WARNING:** Only use this option if you either have internal checks against malicious external sites or you can trust the allowed external sites. You application might be vulnerable to dangerous Tauri command related attacks otherwise.", - "default": [], - "type": "array", - "items": { - "$ref": "#/definitions/RemoteDomainAccessScope" - } - }, "assetProtocol": { "description": "Custom protocol config.", "default": { @@ -2298,43 +2288,6 @@ } ] }, - "RemoteDomainAccessScope": { - "description": "External command access definition.", - "type": "object", - "required": [ - "domain", - "windows" - ], - "properties": { - "scheme": { - "description": "The URL scheme to allow. By default, all schemas are allowed.", - "type": [ - "string", - "null" - ] - }, - "domain": { - "description": "The domain to allow.", - "type": "string" - }, - "windows": { - "description": "The list of window labels this scope applies to.", - "type": "array", - "items": { - "type": "string" - } - }, - "plugins": { - "description": "The list of plugins that are allowed in this scope. The names should be without the `tauri-plugin-` prefix, for example `\"store\"` for `tauri-plugin-store`.", - "default": [], - "type": "array", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false - }, "AssetProtocolConfig": { "description": "Config for the asset custom protocol.\n\nSee more: ", "type": "object", diff --git a/core/tauri-utils/src/config.rs b/core/tauri-utils/src/config.rs index 5a5cb06ead1f..6210d75852c5 100644 --- a/core/tauri-utils/src/config.rs +++ b/core/tauri-utils/src/config.rs @@ -1543,20 +1543,6 @@ pub struct SecurityConfig { /// Your application might be vulnerable to XSS attacks without this Tauri protection. #[serde(default, alias = "dangerous-disable-asset-csp-modification")] pub dangerous_disable_asset_csp_modification: DisabledCspModificationKind, - /// Allow external domains to send command to Tauri. - /// - /// By default, external domains do not have access to `window.__TAURI__`, which means they cannot - /// communicate with the commands defined in Rust. This prevents attacks where an externally - /// loaded malicious or compromised sites could start executing commands on the user's device. - /// - /// This configuration allows a set of external domains to have access to the Tauri commands. - /// When you configure a domain to be allowed to access the IPC, all subpaths are allowed. Subdomains are not allowed. - /// - /// **WARNING:** Only use this option if you either have internal checks against malicious - /// external sites or you can trust the allowed external sites. You application might be - /// vulnerable to dangerous Tauri command related attacks otherwise. - #[serde(default, alias = "dangerous-remote-domain-ipc-access")] - pub dangerous_remote_domain_ipc_access: Vec, /// Custom protocol config. #[serde(default, alias = "asset-protocol")] pub asset_protocol: AssetProtocolConfig, @@ -2611,8 +2597,6 @@ mod build { let dev_csp = opt_lit(self.dev_csp.as_ref()); let freeze_prototype = self.freeze_prototype; let dangerous_disable_asset_csp_modification = &self.dangerous_disable_asset_csp_modification; - let dangerous_remote_domain_ipc_access = - vec_lit(&self.dangerous_remote_domain_ipc_access, identity); let asset_protocol = &self.asset_protocol; literal_struct!( @@ -2622,7 +2606,6 @@ mod build { dev_csp, freeze_prototype, dangerous_disable_asset_csp_modification, - dangerous_remote_domain_ipc_access, asset_protocol ); } @@ -2783,7 +2766,6 @@ mod test { dev_csp: None, freeze_prototype: false, dangerous_disable_asset_csp_modification: DisabledCspModificationKind::Flag(false), - dangerous_remote_domain_ipc_access: Vec::new(), asset_protocol: AssetProtocolConfig::default(), }, tray_icon: None, diff --git a/core/tauri/src/app.rs b/core/tauri/src/app.rs index a5158d5c8ac8..ace8ae719937 100644 --- a/core/tauri/src/app.rs +++ b/core/tauri/src/app.rs @@ -15,7 +15,6 @@ use crate::{ window::{PendingWindow, WindowEvent as RuntimeWindowEvent}, ExitRequestedEventAction, RunEvent as RuntimeRunEvent, }, - scope, sealed::{ManagerBase, RuntimeOrDispatch}, utils::config::Config, utils::{assets::Assets, Env}, @@ -1573,7 +1572,6 @@ impl Builder { app.manage(env); app.manage(Scopes { - ipc: scope::ipc::Scope::new(app.config()), #[cfg(feature = "protocol-asset")] asset_protocol: scope::fs::Scope::new( &app, diff --git a/core/tauri/src/lib.rs b/core/tauri/src/lib.rs index 29a19b8f2a57..ba92d226db2a 100644 --- a/core/tauri/src/lib.rs +++ b/core/tauri/src/lib.rs @@ -857,11 +857,6 @@ pub trait Manager: sealed::ManagerBase { self.state::().inner().clone() } - /// Gets the scope for the IPC. - fn ipc_scope(&self) -> scope::ipc::Scope { - self.state::().inner().ipc.clone() - } - /// Gets the scope for the asset protocol. #[cfg(feature = "protocol-asset")] fn asset_protocol_scope(&self) -> scope::fs::Scope { diff --git a/core/tauri/src/scope/ipc.rs b/core/tauri/src/scope/ipc.rs deleted file mode 100644 index faee2cc36725..000000000000 --- a/core/tauri/src/scope/ipc.rs +++ /dev/null @@ -1,423 +0,0 @@ -// Copyright 2019-2023 Tauri Programme within The Commons Conservancy -// SPDX-License-Identifier: Apache-2.0 -// SPDX-License-Identifier: MIT - -use std::sync::{Arc, Mutex}; - -use crate::{Config, Runtime, Window}; -use url::Url; - -/// IPC access configuration for a remote domain. -#[derive(Debug, Clone)] -pub struct RemoteDomainAccessScope { - scheme: Option, - domain: String, - windows: Vec, - plugins: Vec, -} - -impl RemoteDomainAccessScope { - /// Creates a new access scope. - pub fn new(domain: impl Into) -> Self { - Self { - scheme: None, - domain: domain.into(), - windows: Vec::new(), - plugins: Vec::new(), - } - } - - /// Sets the scheme of the URL to allow in this scope. By default, all schemes with the given domain are allowed. - pub fn allow_on_scheme(mut self, scheme: impl Into) -> Self { - self.scheme.replace(scheme.into()); - self - } - - /// Adds the given window label to the list of windows that uses this scope. - pub fn add_window(mut self, window: impl Into) -> Self { - self.windows.push(window.into()); - self - } - - /// Adds the given plugin to the allowed plugin list. - pub fn add_plugin(mut self, plugin: impl Into) -> Self { - self.plugins.push(plugin.into()); - self - } - - /// Adds the given list of plugins to the allowed plugin list. - pub fn add_plugins(mut self, plugins: I) -> Self - where - I: IntoIterator, - S: Into, - { - self.plugins.extend(plugins.into_iter().map(Into::into)); - self - } - - /// The domain of the URLs that can access this scope. - pub fn domain(&self) -> &str { - &self.domain - } - - /// The list of window labels that can access this scope. - pub fn windows(&self) -> &Vec { - &self.windows - } - - /// The list of plugins enabled by this scope. - pub fn plugins(&self) -> &Vec { - &self.plugins - } -} - -pub(crate) struct RemoteAccessError { - pub matches_window: bool, - pub matches_domain: bool, -} - -/// IPC scope. -#[derive(Clone)] -pub struct Scope { - remote_access: Arc>>, -} - -impl Scope { - pub(crate) fn new(config: &Config) -> Self { - #[allow(unused_mut)] - let mut remote_access: Vec = config - .tauri - .security - .dangerous_remote_domain_ipc_access - .clone() - .into_iter() - .map(|s| RemoteDomainAccessScope { - scheme: s.scheme, - domain: s.domain, - windows: s.windows, - plugins: s.plugins, - }) - .collect(); - - Self { - remote_access: Arc::new(Mutex::new(remote_access)), - } - } - - /// Adds the given configuration for remote access. - /// - /// # Examples - /// - /// ``` - /// use tauri::{Manager, scope::ipc::RemoteDomainAccessScope}; - /// tauri::Builder::default() - /// .setup(|app| { - /// app.ipc_scope().configure_remote_access( - /// RemoteDomainAccessScope::new("tauri.app") - /// .add_window("main") - /// .add_plugins(["path", "event"]) - /// ); - /// Ok(()) - /// }); - /// ``` - pub fn configure_remote_access(&self, access: RemoteDomainAccessScope) { - self.remote_access.lock().unwrap().push(access); - } - - pub(crate) fn remote_access_for( - &self, - window: &Window, - url: &Url, - ) -> Result { - let mut scope = None; - let mut found_scope_for_window = false; - let mut found_scope_for_domain = false; - let label = window.label().to_string(); - - for s in &*self.remote_access.lock().unwrap() { - #[allow(unused_mut)] - let mut matches_window = s.windows.contains(&label); - - let matches_scheme = s - .scheme - .as_ref() - .map(|scheme| scheme == url.scheme()) - .unwrap_or(true); - - let matches_domain = - matches_scheme && url.domain().map(|d| d == s.domain).unwrap_or_default(); - found_scope_for_window = found_scope_for_window || matches_window; - found_scope_for_domain = found_scope_for_domain || matches_domain; - if matches_window && matches_domain && scope.is_none() { - scope.replace(s.clone()); - } - } - - if let Some(s) = scope { - Ok(s) - } else { - Err(RemoteAccessError { - matches_window: found_scope_for_window, - matches_domain: found_scope_for_domain, - }) - } - } -} - -#[cfg(test)] -mod tests { - use tauri_utils::acl::{ - resolved::{CommandKey, ResolvedCommand}, - ExecutionContext, - }; - - use super::RemoteDomainAccessScope; - use crate::{ - ipc::CallbackFn, - test::{assert_ipc_response, mock_builder, mock_context, noop_assets, MockRuntime}, - window::InvokeRequest, - App, Manager, Window, WindowBuilder, - }; - - const PLUGIN_NAME: &str = "test"; - - fn test_context( - request: &InvokeRequest, - scopes: Vec, - ) -> (App, Window) { - let mut ctx = mock_context(noop_assets()); - - ctx.resolved_acl.allowed_commands.insert( - CommandKey { - name: request.cmd.clone(), - context: ExecutionContext::Local, - }, - ResolvedCommand { - windows: vec!["main".into()], - scope: None, - }, - ); - for scope in &scopes { - ctx.resolved_acl.allowed_commands.insert( - CommandKey { - name: request.cmd.clone(), - context: ExecutionContext::Remote { - domain: scope.domain.clone(), - }, - }, - ResolvedCommand { - windows: vec!["main".into()], - scope: None, - }, - ); - } - - let app = mock_builder().build(ctx).unwrap(); - let window = WindowBuilder::new(&app, "main", Default::default()) - .build() - .unwrap(); - - for scope in scopes { - app.ipc_scope().configure_remote_access(scope); - } - - (app, window) - } - - fn path_is_absolute_request() -> InvokeRequest { - let callback = CallbackFn(0); - let error = CallbackFn(1); - - let mut payload = serde_json::Map::new(); - payload.insert( - "path".into(), - serde_json::Value::String(std::env::current_dir().unwrap().display().to_string()), - ); - - InvokeRequest { - cmd: "plugin:path|is_absolute".into(), - callback, - error, - body: serde_json::Value::Object(payload).into(), - headers: Default::default(), - } - } - - fn plugin_test_request() -> InvokeRequest { - let callback = CallbackFn(0); - let error = CallbackFn(1); - - InvokeRequest { - cmd: format!("plugin:{PLUGIN_NAME}|doSomething"), - callback, - error, - body: Default::default(), - headers: Default::default(), - } - } - - #[test] - fn scope_not_defined() { - let request = path_is_absolute_request(); - let (_app, mut window) = test_context( - &request, - vec![RemoteDomainAccessScope::new("app.tauri.app") - .add_window("other") - .add_plugin("path")], - ); - - window.navigate("https://tauri.app".parse().unwrap()); - assert_ipc_response( - &window, - request, - Err(crate::window::ipc_scope_not_found_error_message( - "main", - "https://tauri.app/", - )), - ); - } - - #[test] - fn scope_not_defined_for_window() { - let request = path_is_absolute_request(); - let (_app, mut window) = test_context( - &request, - vec![RemoteDomainAccessScope::new("tauri.app") - .add_window("second") - .add_plugin("path")], - ); - - window.navigate("https://tauri.app".parse().unwrap()); - assert_ipc_response( - &window, - request, - Err(crate::window::ipc_scope_window_error_message("main")), - ); - } - - #[test] - fn scope_not_defined_for_url() { - let request = path_is_absolute_request(); - - let (_app, mut window) = test_context( - &request, - vec![RemoteDomainAccessScope::new("github.com") - .add_window("main") - .add_plugin("path")], - ); - - window.navigate("https://tauri.app".parse().unwrap()); - assert_ipc_response( - &window, - request, - Err(crate::window::ipc_scope_domain_error_message( - "https://tauri.app/", - )), - ); - } - - #[test] - fn subdomain_is_not_allowed() { - let (_app, mut window) = test_context( - &path_is_absolute_request(), - vec![ - RemoteDomainAccessScope::new("tauri.app") - .add_window("main") - .add_plugin("path"), - RemoteDomainAccessScope::new("sub.tauri.app") - .add_window("main") - .add_plugin("path"), - ], - ); - - window.navigate("https://tauri.app".parse().unwrap()); - assert_ipc_response(&window, path_is_absolute_request(), Ok(true)); - - window.navigate("https://blog.tauri.app".parse().unwrap()); - assert_ipc_response( - &window, - path_is_absolute_request(), - Err(crate::window::ipc_scope_domain_error_message( - "https://blog.tauri.app/", - )), - ); - - window.navigate("https://sub.tauri.app".parse().unwrap()); - assert_ipc_response(&window, path_is_absolute_request(), Ok(true)); - - window.window.label = "test".into(); - window.navigate("https://dev.tauri.app".parse().unwrap()); - assert_ipc_response( - &window, - path_is_absolute_request(), - Err(crate::window::ipc_scope_not_found_error_message( - "test", - "https://dev.tauri.app/", - )), - ); - } - - #[test] - fn subpath_is_allowed() { - let request = path_is_absolute_request(); - let (_app, mut window) = test_context( - &request, - vec![RemoteDomainAccessScope::new("tauri.app") - .add_window("main") - .add_plugin("path")], - ); - - window.navigate("https://tauri.app/inner/path".parse().unwrap()); - assert_ipc_response(&window, request, Ok(true)); - } - - #[test] - fn tauri_api_not_allowed() { - let request = path_is_absolute_request(); - let (_app, mut window) = test_context( - &request, - vec![RemoteDomainAccessScope::new("tauri.app").add_window("main")], - ); - - window.navigate("https://tauri.app".parse().unwrap()); - assert_ipc_response( - &window, - request, - Err(crate::window::IPC_SCOPE_DOES_NOT_ALLOW), - ); - } - - #[test] - fn plugin_allowed() { - let request = plugin_test_request(); - let (_app, mut window) = test_context( - &request, - vec![RemoteDomainAccessScope::new("tauri.app") - .add_window("main") - .add_plugin(PLUGIN_NAME)], - ); - - window.navigate("https://tauri.app".parse().unwrap()); - assert_ipc_response( - &window, - request, - Err(format!("plugin {PLUGIN_NAME} not found")), - ); - } - - #[test] - fn plugin_not_allowed() { - let request = plugin_test_request(); - let (_app, mut window) = test_context( - &request, - vec![RemoteDomainAccessScope::new("tauri.app").add_window("main")], - ); - - window.navigate("https://tauri.app".parse().unwrap()); - assert_ipc_response( - &window, - request, - Err(crate::window::IPC_SCOPE_DOES_NOT_ALLOW), - ); - } -} diff --git a/core/tauri/src/scope/mod.rs b/core/tauri/src/scope/mod.rs index fbb886fb4b5e..d2c7b7c8e5cf 100644 --- a/core/tauri/src/scope/mod.rs +++ b/core/tauri/src/scope/mod.rs @@ -4,8 +4,6 @@ /// FS scope. pub mod fs; -/// IPC scope. -pub mod ipc; use std::path::Path; @@ -14,7 +12,6 @@ pub type ScopeEventId = u32; /// Managed state for all the core scopes in a tauri application. pub struct Scopes { - pub(crate) ipc: ipc::Scope, #[cfg(feature = "protocol-asset")] pub(crate) asset_protocol: fs::Scope, } diff --git a/core/tauri/src/window/mod.rs b/core/tauri/src/window/mod.rs index 6cc62cadb883..e603c08a0e70 100644 --- a/core/tauri/src/window/mod.rs +++ b/core/tauri/src/window/mod.rs @@ -2305,24 +2305,6 @@ impl Window { let current_url = self.url(); let is_local = self.is_local_url(¤t_url); - let mut scope_not_found_error_message = - ipc_scope_not_found_error_message(&self.window.label, current_url.as_str()); - let scope = if is_local { - None - } else { - match self.ipc_scope().remote_access_for(&self, ¤t_url) { - Ok(scope) => Some(scope), - Err(e) => { - if e.matches_window { - scope_not_found_error_message = ipc_scope_domain_error_message(current_url.as_str()); - } else if e.matches_domain { - scope_not_found_error_message = ipc_scope_window_error_message(&self.window.label); - } - None - } - } - }; - let custom_responder = self.manager.window.invoke_responder.clone(); let resolver = InvokeResolver::new( @@ -2377,9 +2359,7 @@ impl Window { acl: resolved_acl, }; - if !is_local && scope.is_none() { - invoke.resolver.reject(scope_not_found_error_message); - } else if request.cmd.starts_with("plugin:") { + if request.cmd.starts_with("plugin:") { if request.cmd != crate::ipc::channel::FETCH_CHANNEL_DATA_COMMAND && invoke.acl.is_none() { invoke.resolver.reject("NOT ALLOWED"); return; @@ -2394,16 +2374,6 @@ impl Window { .map(|c| c.to_string()) .unwrap_or_else(String::new); - if !(is_local - || plugin == crate::ipc::channel::CHANNEL_PLUGIN_NAME - || scope - .map(|s| s.plugins().contains(&plugin.into())) - .unwrap_or(true)) - { - invoke.resolver.reject(IPC_SCOPE_DOES_NOT_ALLOW); - return; - } - let command = invoke.message.command.clone(); #[cfg(mobile)] @@ -2774,20 +2744,6 @@ impl From for EffectsBuilder { } } -pub(crate) const IPC_SCOPE_DOES_NOT_ALLOW: &str = "Not allowed by the scope"; - -pub(crate) fn ipc_scope_not_found_error_message(label: &str, url: &str) -> String { - format!("Scope not defined for window `{label}` and URL `{url}`. See https://tauri.app/v1/api/config/#securityconfig.dangerousremotedomainipcaccess and https://docs.rs/tauri/1/tauri/scope/struct.IpcScope.html#method.configure_remote_access") -} - -pub(crate) fn ipc_scope_window_error_message(label: &str) -> String { - format!("Scope not defined for window `{}`. See https://tauri.app/v1/api/config/#securityconfig.dangerousremotedomainipcaccess and https://docs.rs/tauri/1/tauri/scope/struct.IpcScope.html#method.configure_remote_access", label) -} - -pub(crate) fn ipc_scope_domain_error_message(url: &str) -> String { - format!("Scope not defined for URL `{url}`. See https://tauri.app/v1/api/config/#securityconfig.dangerousremotedomainipcaccess and https://docs.rs/tauri/1/tauri/scope/struct.IpcScope.html#method.configure_remote_access") -} - #[cfg(test)] mod tests { #[test] diff --git a/tooling/cli/schema.json b/tooling/cli/schema.json index ddc1fff4291c..aa64fe31f97b 100644 --- a/tooling/cli/schema.json +++ b/tooling/cli/schema.json @@ -96,7 +96,6 @@ "scope": [] }, "dangerousDisableAssetCspModification": false, - "dangerousRemoteDomainIpcAccess": [], "freezePrototype": false }, "windows": [] @@ -254,7 +253,6 @@ "scope": [] }, "dangerousDisableAssetCspModification": false, - "dangerousRemoteDomainIpcAccess": [], "freezePrototype": false }, "allOf": [ @@ -2227,14 +2225,6 @@ } ] }, - "dangerousRemoteDomainIpcAccess": { - "description": "Allow external domains to send command to Tauri.\n\nBy default, external domains do not have access to `window.__TAURI__`, which means they cannot communicate with the commands defined in Rust. This prevents attacks where an externally loaded malicious or compromised sites could start executing commands on the user's device.\n\nThis configuration allows a set of external domains to have access to the Tauri commands. When you configure a domain to be allowed to access the IPC, all subpaths are allowed. Subdomains are not allowed.\n\n**WARNING:** Only use this option if you either have internal checks against malicious external sites or you can trust the allowed external sites. You application might be vulnerable to dangerous Tauri command related attacks otherwise.", - "default": [], - "type": "array", - "items": { - "$ref": "#/definitions/RemoteDomainAccessScope" - } - }, "assetProtocol": { "description": "Custom protocol config.", "default": { @@ -2298,43 +2288,6 @@ } ] }, - "RemoteDomainAccessScope": { - "description": "External command access definition.", - "type": "object", - "required": [ - "domain", - "windows" - ], - "properties": { - "scheme": { - "description": "The URL scheme to allow. By default, all schemas are allowed.", - "type": [ - "string", - "null" - ] - }, - "domain": { - "description": "The domain to allow.", - "type": "string" - }, - "windows": { - "description": "The list of window labels this scope applies to.", - "type": "array", - "items": { - "type": "string" - } - }, - "plugins": { - "description": "The list of plugins that are allowed in this scope. The names should be without the `tauri-plugin-` prefix, for example `\"store\"` for `tauri-plugin-store`.", - "default": [], - "type": "array", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false - }, "AssetProtocolConfig": { "description": "Config for the asset custom protocol.\n\nSee more: ", "type": "object", From 6af1c79d2321970bd0fa10b463d106c2e469b604 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 17 Jan 2024 15:13:32 -0300 Subject: [PATCH 53/69] lint --- core/tauri-utils/src/acl/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/tauri-utils/src/acl/build.rs b/core/tauri-utils/src/acl/build.rs index 1a956f0fc80a..1c3fca676849 100644 --- a/core/tauri-utils/src/acl/build.rs +++ b/core/tauri-utils/src/acl/build.rs @@ -307,7 +307,7 @@ commands.deny = ["{command}"] "###, command = command, slugified_command = slugified_command, - schema_path = schema_path.display().to_string().replace("\\", "\\\\") + schema_path = schema_path.display().to_string().replace('\\', "\\\\") ); std::fs::write(path.join(format!("{command}.toml")), toml) From 25e5afcd1843997b6f2bfd7314cfef0e65b5c3ec Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 17 Jan 2024 15:18:14 -0300 Subject: [PATCH 54/69] fix asset scope usage --- core/tauri/src/app.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/tauri/src/app.rs b/core/tauri/src/app.rs index ace8ae719937..118ed57dadbb 100644 --- a/core/tauri/src/app.rs +++ b/core/tauri/src/app.rs @@ -1573,7 +1573,7 @@ impl Builder { app.manage(Scopes { #[cfg(feature = "protocol-asset")] - asset_protocol: scope::fs::Scope::new( + asset_protocol: crate::scope::fs::Scope::new( &app, &app.config().tauri.security.asset_protocol.scope, )?, From ac6d869b667b99ed475a5accd29113c42b9d9523 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 17 Jan 2024 16:28:56 -0300 Subject: [PATCH 55/69] create out dir [skip ci] --- core/tauri-build/src/acl.rs | 7 ++++--- core/tauri-utils/src/acl/build.rs | 5 ++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/core/tauri-build/src/acl.rs b/core/tauri-build/src/acl.rs index f08a5db77ac5..47b278fbdbd4 100644 --- a/core/tauri-build/src/acl.rs +++ b/core/tauri-build/src/acl.rs @@ -4,7 +4,7 @@ use std::{ collections::BTreeMap, - fs::File, + fs::{create_dir_all, File}, io::{BufWriter, Write}, path::PathBuf, }; @@ -80,9 +80,10 @@ fn capabilities_schema(plugin_manifests: &BTreeMap) -> RootSch pub fn generate_schema(plugin_manifests: &BTreeMap) -> Result<()> { let schema = capabilities_schema(plugin_manifests); let schema_str = serde_json::to_string_pretty(&schema).unwrap(); - let out_path = PathBuf::from("capabilities").join(CAPABILITIES_SCHEMA_FILE_NAME); + let out_dir = PathBuf::from("capabilities"); + create_dir_all(&out_dir).context("unable to create schema output directory")?; - let mut schema_file = BufWriter::new(File::create(out_path)?); + let mut schema_file = BufWriter::new(File::create(out_dir.join(CAPABILITIES_SCHEMA_FILE_NAME))?); write!(schema_file, "{schema_str}")?; Ok(()) } diff --git a/core/tauri-utils/src/acl/build.rs b/core/tauri-utils/src/acl/build.rs index 1c3fca676849..aff903ed648a 100644 --- a/core/tauri-utils/src/acl/build.rs +++ b/core/tauri-utils/src/acl/build.rs @@ -218,8 +218,11 @@ pub fn generate_schema>( let schema = permissions_schema(permissions); let schema_str = serde_json::to_string_pretty(&schema).unwrap(); + let out_dir = out_dir.as_ref(); + create_dir_all(&out_dir).expect("unable to create schema output directory"); + let mut schema_file = BufWriter::new( - File::create(out_dir.as_ref().join(PERMISSION_SCHEMA_FILE_NAME)).map_err(Error::CreateFile)?, + File::create(out_dir.join(PERMISSION_SCHEMA_FILE_NAME)).map_err(Error::CreateFile)?, ); write!(schema_file, "{schema_str}").map_err(Error::WriteFile)?; Ok(()) From 9a32347a73be24827873dc970899d87cf3ed7dbe Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Thu, 18 Jan 2024 08:37:58 -0300 Subject: [PATCH 56/69] reuse cargo_pkg_name [skip ci] --- core/tauri-plugin/src/build/mod.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/core/tauri-plugin/src/build/mod.rs b/core/tauri-plugin/src/build/mod.rs index 282c8a1115ad..7d593671ff43 100644 --- a/core/tauri-plugin/src/build/mod.rs +++ b/core/tauri-plugin/src/build/mod.rs @@ -47,10 +47,7 @@ impl<'a> Builder<'a> { acl::build::autogenerate_command_permissions(commands_dir, self.commands, ""); } - let permissions = acl::build::define_permissions( - "./permissions/**/*.*", - &std::env::var("CARGO_PKG_NAME").unwrap(), - )?; + let permissions = acl::build::define_permissions("./permissions/**/*.*", &name)?; acl::build::generate_schema(&permissions, "./permissions")?; let metadata = find_metadata()?; From 38f6b99bae72e06ed007975c41a2e0070c719780 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Thu, 18 Jan 2024 08:47:46 -0300 Subject: [PATCH 57/69] capability window glob pattern [skip ci] --- core/tauri-utils/src/acl/resolved.rs | 31 ++++++++++------ core/tauri/src/command/authority.rs | 2 +- examples/api/dist/assets/index.js | 36 +++++++++---------- .../api/src-tauri/capabilities/run-app.toml | 2 +- examples/api/src/views/Window.svelte | 28 +++++++++++---- 5 files changed, 63 insertions(+), 36 deletions(-) diff --git a/core/tauri-utils/src/acl/resolved.rs b/core/tauri-utils/src/acl/resolved.rs index 37dacb4d5f44..5dbe8925f2ed 100644 --- a/core/tauri-utils/src/acl/resolved.rs +++ b/core/tauri-utils/src/acl/resolved.rs @@ -22,7 +22,7 @@ pub type ScopeKey = usize; #[derive(Debug, Clone)] pub struct ResolvedCommand { /// The list of window label patterns that is allowed to run this command. - pub windows: Vec, + pub windows: Vec, /// The reference of the scope that is associated with this command. See [`Resolved#structfield.scopes`]. pub scope: Option, } @@ -169,27 +169,27 @@ impl Resolved { allowed_commands: allowed_commands .into_iter() .map(|(key, cmd)| { - ( + Ok(( key, ResolvedCommand { - windows: cmd.windows.into_iter().collect(), + windows: parse_window_patterns(cmd.windows)?, scope: cmd.resolved_scope_key, }, - ) + )) }) - .collect(), + .collect::>()?, denied_commands: denied_commands .into_iter() .map(|(key, cmd)| { - ( + Ok(( key, ResolvedCommand { - windows: cmd.windows.into_iter().collect(), + windows: parse_window_patterns(cmd.windows)?, scope: cmd.resolved_scope_key, }, - ) + )) }) - .collect(), + .collect::>()?, command_scope: resolved_scopes, global_scope, }; @@ -198,6 +198,14 @@ impl Resolved { } } +fn parse_window_patterns(windows: HashSet) -> Result, Error> { + let mut patterns = Vec::new(); + for window in windows { + patterns.push(glob::Pattern::new(&window)?); + } + Ok(patterns) +} + #[derive(Debug, Default)] struct ResolvedCommandTemp { pub windows: HashSet, @@ -324,7 +332,10 @@ mod build { impl ToTokens for ResolvedCommand { fn to_tokens(&self, tokens: &mut TokenStream) { - let windows = vec_lit(&self.windows, str_lit); + let windows = vec_lit(&self.windows, |window| { + let w = window.as_str(); + quote!(#w.parse().unwrap()) + }); let scope = opt_lit(self.scope.as_ref()); literal_struct!(tokens, ResolvedCommand, windows, scope) } diff --git a/core/tauri/src/command/authority.rs b/core/tauri/src/command/authority.rs index b53e6daff725..b6c15566bdf8 100644 --- a/core/tauri/src/command/authority.rs +++ b/core/tauri/src/command/authority.rs @@ -60,7 +60,7 @@ impl RuntimeAuthority { self .allowed_commands .get(&key) - .filter(|allowed| allowed.windows.contains(window)) + .filter(|allowed| allowed.windows.iter().any(|w| w.matches(window))) } } } diff --git a/examples/api/dist/assets/index.js b/examples/api/dist/assets/index.js index 28b029f56903..591cd0f613e6 100644 --- a/examples/api/dist/assets/index.js +++ b/examples/api/dist/assets/index.js @@ -1,9 +1,9 @@ -var yr=Object.defineProperty;var vr=(t,e,n)=>e in t?yr(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var _t=(t,e,n)=>(vr(t,typeof e!="symbol"?e+"":e,n),n);(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))l(s);new MutationObserver(s=>{for(const u of s)if(u.type==="childList")for(const d of u.addedNodes)d.tagName==="LINK"&&d.rel==="modulepreload"&&l(d)}).observe(document,{childList:!0,subtree:!0});function n(s){const u={};return s.integrity&&(u.integrity=s.integrity),s.referrerPolicy&&(u.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?u.credentials="include":s.crossOrigin==="anonymous"?u.credentials="omit":u.credentials="same-origin",u}function l(s){if(s.ep)return;s.ep=!0;const u=n(s);fetch(s.href,u)}})();function ie(){}function sr(t){return t()}function Ms(){return Object.create(null)}function Ce(t){t.forEach(sr)}function rr(t){return typeof t=="function"}function je(t,e){return t!=t?e==e:t!==e||t&&typeof t=="object"||typeof t=="function"}let Vi;function Cr(t,e){return t===e?!0:(Vi||(Vi=document.createElement("a")),Vi.href=e,t===Vi.href)}function Sr(t){return Object.keys(t).length===0}function Lr(t,...e){if(t==null){for(const l of e)l(void 0);return ie}const n=t.subscribe(...e);return n.unsubscribe?()=>n.unsubscribe():n}function Ar(t,e,n){t.$$.on_destroy.push(Lr(e,n))}function i(t,e){t.appendChild(e)}function C(t,e,n){t.insertBefore(e,n||null)}function v(t){t.parentNode&&t.parentNode.removeChild(t)}function Je(t,e){for(let n=0;nt.removeEventListener(e,n,l)}function Ps(t){return function(e){return e.preventDefault(),t.call(this,e)}}function a(t,e,n){n==null?t.removeAttribute(e):t.getAttribute(e)!==n&&t.setAttribute(e,n)}function Q(t){return t===""?null:+t}function Pr(t){return Array.from(t.childNodes)}function re(t,e){e=""+e,t.data!==e&&(t.data=e)}function I(t,e){t.value=e??""}function xt(t,e,n,l){n==null?t.style.removeProperty(e):t.style.setProperty(e,n,l?"important":"")}function Qe(t,e,n){for(let l=0;l{const s=t.$$.callbacks[e];if(s){const u=Er(e,n,{cancelable:l});return s.slice().forEach(d=>{d.call(t,u)}),!u.defaultPrevented}return!0}}const tn=[],sn=[];let nn=[];const El=[],or=Promise.resolve();let Tl=!1;function cr(){Tl||(Tl=!0,or.then(hr))}function Ts(){return cr(),or}function wt(t){nn.push(t)}function dr(t){El.push(t)}const Sl=new Set;let $t=0;function hr(){if($t!==0)return;const t=On;do{try{for(;$tt.indexOf(l)===-1?e.push(l):n.push(l)),n.forEach(l=>l()),nn=e}const qi=new Set;let zt;function Wr(){zt={r:0,c:[],p:zt}}function Ir(){zt.r||Ce(zt.c),zt=zt.p}function rn(t,e){t&&t.i&&(qi.delete(t),t.i(e))}function Wn(t,e,n,l){if(t&&t.o){if(qi.has(t))return;qi.add(t),zt.c.push(()=>{qi.delete(t),l&&(n&&t.d(1),l())}),t.o(e)}else l&&l()}function fe(t){return(t==null?void 0:t.length)!==void 0?t:Array.from(t)}function fr(t,e,n){const l=t.$$.props[e];l!==void 0&&(t.$$.bound[l]=n,n(t.$$.ctx[l]))}function In(t){t&&t.c()}function an(t,e,n){const{fragment:l,after_update:s}=t.$$;l&&l.m(e,n),wt(()=>{const u=t.$$.on_mount.map(sr).filter(rr);t.$$.on_destroy?t.$$.on_destroy.push(...u):Ce(u),t.$$.on_mount=[]}),s.forEach(wt)}function un(t,e){const n=t.$$;n.fragment!==null&&(Or(n.after_update),Ce(n.on_destroy),n.fragment&&n.fragment.d(e),n.on_destroy=n.fragment=null,n.ctx=[])}function Rr(t,e){t.$$.dirty[0]===-1&&(tn.push(t),cr(),t.$$.dirty.fill(0)),t.$$.dirty[e/31|0]|=1<{const y=k.length?k[0]:A;return h.ctx&&s(h.ctx[_],h.ctx[_]=y)&&(!h.skip_bound&&h.bound[_]&&h.bound[_](y),w&&Rr(t,_)),A}):[],h.update(),w=!0,Ce(h.before_update),h.fragment=l?l(h.ctx):!1,e.target){if(e.hydrate){const _=Pr(e.target);h.fragment&&h.fragment.l(_),_.forEach(v)}else h.fragment&&h.fragment.c();e.intro&&rn(t.$$.fragment),an(t,e.target,e.anchor),hr()}zn(c)}class xe{constructor(){_t(this,"$$");_t(this,"$$set")}$destroy(){un(this,1),this.$destroy=ie}$on(e,n){if(!rr(n))return ie;const l=this.$$.callbacks[e]||(this.$$.callbacks[e]=[]);return l.push(n),()=>{const s=l.indexOf(n);s!==-1&&l.splice(s,1)}}$set(e){this.$$set&&!Sr(e)&&(this.$$.skip_bound=!0,this.$$set(e),this.$$.skip_bound=!1)}}const Dr="4";typeof window<"u"&&(window.__svelte||(window.__svelte={v:new Set})).v.add(Dr);const en=[];function Fr(t,e=ie){let n;const l=new Set;function s(o){if(je(t,o)&&(t=o,n)){const c=!en.length;for(const h of l)h[1](),en.push(h,t);if(c){for(let h=0;h{l.delete(h),l.size===0&&n&&(n(),n=null)}}return{set:s,update:u,subscribe:d}}function Rn(t,e,n,l){if(n==="a"&&!l)throw new TypeError("Private accessor was defined without a getter");if(typeof e=="function"?t!==e||!l:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return n==="m"?l:n==="a"?l.call(t):l?l.value:e.get(t)}function Xi(t,e,n,l,s){if(l==="m")throw new TypeError("Private method is not writable");if(l==="a"&&!s)throw new TypeError("Private accessor was defined without a setter");if(typeof e=="function"?t!==e||!s:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return l==="a"?s.call(t,n):s?s.value=n:e.set(t,n),n}var Tn,Ni;function pr(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}class Il{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,Tn.set(this,()=>{}),this.id=pr(e=>{Rn(this,Tn,"f").call(this,e)})}set onmessage(e){Xi(this,Tn,e,"f")}get onmessage(){return Rn(this,Tn,"f")}toJSON(){return`__CHANNEL__:${this.id}`}}Tn=new WeakMap;async function m(t,e={},n){return window.__TAURI_INTERNALS__.invoke(t,e,n)}class mr{get rid(){return Rn(this,Ni,"f")}constructor(e){Ni.set(this,void 0),Xi(this,Ni,e,"f")}async close(){return m("plugin:resources|close",{rid:this.rid})}}Ni=new WeakMap;async function Hr(){return m("plugin:app|version")}async function Ur(){return m("plugin:app|name")}async function Br(){return m("plugin:app|tauri_version")}async function Vr(){return m("plugin:app|app_show")}async function qr(){return m("plugin:app|app_hide")}function Nr(t){let e,n,l,s,u,d,o,c,h,w,_,A,k,y,L,M,B,D,O,P,E,z,R,J;return{c(){e=r("div"),n=r("p"),n.innerHTML=`This is a demo of Tauri's API capabilities using the @tauri-apps/api package. It's used as the main validation app, serving as the test bed of our +var yr=Object.defineProperty;var vr=(t,e,n)=>e in t?yr(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var bt=(t,e,n)=>(vr(t,typeof e!="symbol"?e+"":e,n),n);(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))l(s);new MutationObserver(s=>{for(const u of s)if(u.type==="childList")for(const d of u.addedNodes)d.tagName==="LINK"&&d.rel==="modulepreload"&&l(d)}).observe(document,{childList:!0,subtree:!0});function n(s){const u={};return s.integrity&&(u.integrity=s.integrity),s.referrerPolicy&&(u.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?u.credentials="include":s.crossOrigin==="anonymous"?u.credentials="omit":u.credentials="same-origin",u}function l(s){if(s.ep)return;s.ep=!0;const u=n(s);fetch(s.href,u)}})();function ie(){}function sr(t){return t()}function Ms(){return Object.create(null)}function Ce(t){t.forEach(sr)}function rr(t){return typeof t=="function"}function je(t,e){return t!=t?e==e:t!==e||t&&typeof t=="object"||typeof t=="function"}let Vi;function Cr(t,e){return t===e?!0:(Vi||(Vi=document.createElement("a")),Vi.href=e,t===Vi.href)}function Sr(t){return Object.keys(t).length===0}function Lr(t,...e){if(t==null){for(const l of e)l(void 0);return ie}const n=t.subscribe(...e);return n.unsubscribe?()=>n.unsubscribe():n}function Ar(t,e,n){t.$$.on_destroy.push(Lr(e,n))}function i(t,e){t.appendChild(e)}function C(t,e,n){t.insertBefore(e,n||null)}function v(t){t.parentNode&&t.parentNode.removeChild(t)}function Je(t,e){for(let n=0;nt.removeEventListener(e,n,l)}function Ps(t){return function(e){return e.preventDefault(),t.call(this,e)}}function a(t,e,n){n==null?t.removeAttribute(e):t.getAttribute(e)!==n&&t.setAttribute(e,n)}function Q(t){return t===""?null:+t}function Pr(t){return Array.from(t.childNodes)}function re(t,e){e=""+e,t.data!==e&&(t.data=e)}function I(t,e){t.value=e??""}function $t(t,e,n,l){n==null?t.style.removeProperty(e):t.style.setProperty(e,n,l?"important":"")}function Qe(t,e,n){for(let l=0;l{const s=t.$$.callbacks[e];if(s){const u=Er(e,n,{cancelable:l});return s.slice().forEach(d=>{d.call(t,u)}),!u.defaultPrevented}return!0}}const nn=[],rn=[];let ln=[];const El=[],or=Promise.resolve();let Tl=!1;function cr(){Tl||(Tl=!0,or.then(hr))}function Ts(){return cr(),or}function kt(t){ln.push(t)}function dr(t){El.push(t)}const Sl=new Set;let en=0;function hr(){if(en!==0)return;const t=On;do{try{for(;ent.indexOf(l)===-1?e.push(l):n.push(l)),n.forEach(l=>l()),ln=e}const qi=new Set;let Ot;function Wr(){Ot={r:0,c:[],p:Ot}}function Ir(){Ot.r||Ce(Ot.c),Ot=Ot.p}function an(t,e){t&&t.i&&(qi.delete(t),t.i(e))}function Wn(t,e,n,l){if(t&&t.o){if(qi.has(t))return;qi.add(t),Ot.c.push(()=>{qi.delete(t),l&&(n&&t.d(1),l())}),t.o(e)}else l&&l()}function fe(t){return(t==null?void 0:t.length)!==void 0?t:Array.from(t)}function fr(t,e,n){const l=t.$$.props[e];l!==void 0&&(t.$$.bound[l]=n,n(t.$$.ctx[l]))}function In(t){t&&t.c()}function un(t,e,n){const{fragment:l,after_update:s}=t.$$;l&&l.m(e,n),kt(()=>{const u=t.$$.on_mount.map(sr).filter(rr);t.$$.on_destroy?t.$$.on_destroy.push(...u):Ce(u),t.$$.on_mount=[]}),s.forEach(kt)}function on(t,e){const n=t.$$;n.fragment!==null&&(Or(n.after_update),Ce(n.on_destroy),n.fragment&&n.fragment.d(e),n.on_destroy=n.fragment=null,n.ctx=[])}function Rr(t,e){t.$$.dirty[0]===-1&&(nn.push(t),cr(),t.$$.dirty.fill(0)),t.$$.dirty[e/31|0]|=1<{const y=k.length?k[0]:A;return h.ctx&&s(h.ctx[_],h.ctx[_]=y)&&(!h.skip_bound&&h.bound[_]&&h.bound[_](y),w&&Rr(t,_)),A}):[],h.update(),w=!0,Ce(h.before_update),h.fragment=l?l(h.ctx):!1,e.target){if(e.hydrate){const _=Pr(e.target);h.fragment&&h.fragment.l(_),_.forEach(v)}else h.fragment&&h.fragment.c();e.intro&&an(t.$$.fragment),un(t,e.target,e.anchor),hr()}zn(c)}class xe{constructor(){bt(this,"$$");bt(this,"$$set")}$destroy(){on(this,1),this.$destroy=ie}$on(e,n){if(!rr(n))return ie;const l=this.$$.callbacks[e]||(this.$$.callbacks[e]=[]);return l.push(n),()=>{const s=l.indexOf(n);s!==-1&&l.splice(s,1)}}$set(e){this.$$set&&!Sr(e)&&(this.$$.skip_bound=!0,this.$$set(e),this.$$.skip_bound=!1)}}const Dr="4";typeof window<"u"&&(window.__svelte||(window.__svelte={v:new Set})).v.add(Dr);const tn=[];function Fr(t,e=ie){let n;const l=new Set;function s(o){if(je(t,o)&&(t=o,n)){const c=!tn.length;for(const h of l)h[1](),tn.push(h,t);if(c){for(let h=0;h{l.delete(h),l.size===0&&n&&(n(),n=null)}}return{set:s,update:u,subscribe:d}}function Rn(t,e,n,l){if(n==="a"&&!l)throw new TypeError("Private accessor was defined without a getter");if(typeof e=="function"?t!==e||!l:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return n==="m"?l:n==="a"?l.call(t):l?l.value:e.get(t)}function Xi(t,e,n,l,s){if(l==="m")throw new TypeError("Private method is not writable");if(l==="a"&&!s)throw new TypeError("Private accessor was defined without a setter");if(typeof e=="function"?t!==e||!s:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return l==="a"?s.call(t,n):s?s.value=n:e.set(t,n),n}var Tn,Ni;function pr(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}class Il{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,Tn.set(this,()=>{}),this.id=pr(e=>{Rn(this,Tn,"f").call(this,e)})}set onmessage(e){Xi(this,Tn,e,"f")}get onmessage(){return Rn(this,Tn,"f")}toJSON(){return`__CHANNEL__:${this.id}`}}Tn=new WeakMap;async function m(t,e={},n){return window.__TAURI_INTERNALS__.invoke(t,e,n)}class mr{get rid(){return Rn(this,Ni,"f")}constructor(e){Ni.set(this,void 0),Xi(this,Ni,e,"f")}async close(){return m("plugin:resources|close",{rid:this.rid})}}Ni=new WeakMap;async function Hr(){return m("plugin:app|version")}async function Ur(){return m("plugin:app|name")}async function Br(){return m("plugin:app|tauri_version")}async function Vr(){return m("plugin:app|app_show")}async function qr(){return m("plugin:app|app_hide")}function Nr(t){let e,n,l,s,u,d,o,c,h,w,_,A,k,y,L,M,B,D,O,P,E,z,R,J;return{c(){e=r("div"),n=r("p"),n.innerHTML=`This is a demo of Tauri's API capabilities using the @tauri-apps/api package. It's used as the main validation app, serving as the test bed of our development process. In the future, this app will be used on Tauri's integration tests.`,l=p(),s=r("br"),u=p(),d=r("br"),o=p(),c=r("pre"),h=b(" App name: "),w=r("code"),_=b(t[2]),A=b(` App version: `),k=r("code"),y=b(t[0]),L=b(` Tauri version: `),M=r("code"),B=b(t[1]),D=b(` - `),O=p(),P=r("br"),E=p(),z=r("button"),z.textContent="Context menu",a(z,"class","btn")},m(V,Z){C(V,e,Z),i(e,n),i(e,l),i(e,s),i(e,u),i(e,d),i(e,o),i(e,c),i(c,h),i(c,w),i(w,_),i(c,A),i(c,k),i(k,y),i(c,L),i(c,M),i(M,B),i(c,D),i(e,O),i(e,P),i(e,E),i(e,z),R||(J=S(z,"click",t[3]),R=!0)},p(V,[Z]){Z&4&&re(_,V[2]),Z&1&&re(y,V[0]),Z&2&&re(B,V[1])},i:ie,o:ie,d(V){V&&v(e),R=!1,J()}}}function jr(t,e,n){let l="1.0.0",s="1.0.0",u="Unknown";Ur().then(o=>{n(2,u=o)}),Hr().then(o=>{n(0,l=o)}),Br().then(o=>{n(1,s=o)});function d(){m("popup_context_menu")}return[l,s,u,d]}class Gr extends xe{constructor(e){super(),Ze(this,e,jr,Nr,je,{})}}var Oe;(function(t){t.WINDOW_RESIZED="tauri://resize",t.WINDOW_MOVED="tauri://move",t.WINDOW_CLOSE_REQUESTED="tauri://close-requested",t.WINDOW_CREATED="tauri://window-created",t.WINDOW_DESTROYED="tauri://destroyed",t.WINDOW_FOCUS="tauri://focus",t.WINDOW_BLUR="tauri://blur",t.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",t.WINDOW_THEME_CHANGED="tauri://theme-changed",t.WINDOW_FILE_DROP="tauri://file-drop",t.WINDOW_FILE_DROP_HOVER="tauri://file-drop-hover",t.WINDOW_FILE_DROP_CANCELLED="tauri://file-drop-cancelled"})(Oe||(Oe={}));async function gr(t,e){await m("plugin:event|unlisten",{event:t,eventId:e})}async function Rl(t,e,n){return m("plugin:event|listen",{event:t,windowLabel:n==null?void 0:n.target,handler:pr(e)}).then(l=>async()=>gr(t,l))}async function Kr(t,e,n){return Rl(t,l=>{e(l),gr(t,l.id).catch(()=>{})},n)}async function _r(t,e,n){await m("plugin:event|emit",{event:t,windowLabel:n==null?void 0:n.target,payload:e})}function Xr(t){let e,n,l,s,u,d,o,c;return{c(){e=r("div"),n=r("button"),n.textContent="Call Log API",l=p(),s=r("button"),s.textContent="Call Request (async) API",u=p(),d=r("button"),d.textContent="Send event to Rust",a(n,"class","btn"),a(n,"id","log"),a(s,"class","btn"),a(s,"id","request"),a(d,"class","btn"),a(d,"id","event")},m(h,w){C(h,e,w),i(e,n),i(e,l),i(e,s),i(e,u),i(e,d),o||(c=[S(n,"click",t[0]),S(s,"click",t[1]),S(d,"click",t[2])],o=!0)},p:ie,i:ie,o:ie,d(h){h&&v(e),o=!1,Ce(c)}}}function Yr(t,e,n){let{onMessage:l}=e,s;Ki(async()=>{s=await Rl("rust-event",l)}),ar(()=>{s&&s()});function u(){m("log_operation",{event:"tauri-click",payload:"this payload is optional because we used Option in Rust"})}function d(){m("perform_request",{endpoint:"dummy endpoint arg",body:{id:5,name:"test"}}).then(l).catch(l)}function o(){_r("js-event","this is the payload string")}return t.$$set=c=>{"onMessage"in c&&n(3,l=c.onMessage)},[u,d,o,l]}class Qr extends xe{constructor(e){super(),Ze(this,e,Yr,Xr,je,{onMessage:3})}}class zl{constructor(e,n){this.type="Logical",this.width=e,this.height=n}}class ln{constructor(e,n){this.type="Physical",this.width=e,this.height=n}toLogical(e){return new zl(this.width/e,this.height/e)}}class Jr{constructor(e,n){this.type="Logical",this.x=e,this.y=n}}class it{constructor(e,n){this.type="Physical",this.x=e,this.y=n}toLogical(e){return new Jr(this.x/e,this.y/e)}}var Yi;(function(t){t[t.Critical=1]="Critical",t[t.Informational=2]="Informational"})(Yi||(Yi={}));class Zr{constructor(e){this._preventDefault=!1,this.event=e.event,this.windowLabel=e.windowLabel,this.id=e.id}preventDefault(){this._preventDefault=!0}isPreventDefault(){return this._preventDefault}}var Qi;(function(t){t.None="none",t.Normal="normal",t.Indeterminate="indeterminate",t.Paused="paused",t.Error="error"})(Qi||(Qi={}));function br(){return new Dn(window.__TAURI_INTERNALS__.metadata.currentWindow.label,{skip:!0})}function Ll(){return window.__TAURI_INTERNALS__.metadata.windows.map(t=>new Dn(t.label,{skip:!0}))}const zs=["tauri://created","tauri://error"];class Dn{constructor(e,n={}){this.label=e,this.listeners=Object.create(null),n!=null&&n.skip||m("plugin:window|create",{options:{...n,label:e}}).then(async()=>this.emit("tauri://created")).catch(async l=>this.emit("tauri://error",l))}static getByLabel(e){return Ll().some(n=>n.label===e)?new Dn(e,{skip:!0}):null}static getCurrent(){return br()}static getAll(){return Ll()}static async getFocusedWindow(){for(const e of Ll())if(await e.isFocused())return e;return null}async listen(e,n){return this._handleTauriEvent(e,n)?Promise.resolve(()=>{const l=this.listeners[e];l.splice(l.indexOf(n),1)}):Rl(e,n,{target:this.label})}async once(e,n){return this._handleTauriEvent(e,n)?Promise.resolve(()=>{const l=this.listeners[e];l.splice(l.indexOf(n),1)}):Kr(e,n,{target:this.label})}async emit(e,n){if(zs.includes(e)){for(const l of this.listeners[e]||[])l({event:e,id:-1,windowLabel:this.label,payload:n});return Promise.resolve()}return _r(e,n,{target:this.label})}_handleTauriEvent(e,n){return zs.includes(e)?(e in this.listeners?this.listeners[e].push(n):this.listeners[e]=[n],!0):!1}async scaleFactor(){return m("plugin:window|scale_factor",{label:this.label})}async innerPosition(){return m("plugin:window|inner_position",{label:this.label}).then(({x:e,y:n})=>new it(e,n))}async outerPosition(){return m("plugin:window|outer_position",{label:this.label}).then(({x:e,y:n})=>new it(e,n))}async innerSize(){return m("plugin:window|inner_size",{label:this.label}).then(({width:e,height:n})=>new ln(e,n))}async outerSize(){return m("plugin:window|outer_size",{label:this.label}).then(({width:e,height:n})=>new ln(e,n))}async isFullscreen(){return m("plugin:window|is_fullscreen",{label:this.label})}async isMinimized(){return m("plugin:window|is_minimized",{label:this.label})}async isMaximized(){return m("plugin:window|is_maximized",{label:this.label})}async isFocused(){return m("plugin:window|is_focused",{label:this.label})}async isDecorated(){return m("plugin:window|is_decorated",{label:this.label})}async isResizable(){return m("plugin:window|is_resizable",{label:this.label})}async isMaximizable(){return m("plugin:window|is_maximizable",{label:this.label})}async isMinimizable(){return m("plugin:window|is_minimizable",{label:this.label})}async isClosable(){return m("plugin:window|is_closable",{label:this.label})}async isVisible(){return m("plugin:window|is_visible",{label:this.label})}async title(){return m("plugin:window|title",{label:this.label})}async theme(){return m("plugin:window|theme",{label:this.label})}async center(){return m("plugin:window|center",{label:this.label})}async requestUserAttention(e){let n=null;return e&&(e===Yi.Critical?n={type:"Critical"}:n={type:"Informational"}),m("plugin:window|request_user_attention",{label:this.label,value:n})}async setResizable(e){return m("plugin:window|set_resizable",{label:this.label,value:e})}async setMaximizable(e){return m("plugin:window|set_maximizable",{label:this.label,value:e})}async setMinimizable(e){return m("plugin:window|set_minimizable",{label:this.label,value:e})}async setClosable(e){return m("plugin:window|set_closable",{label:this.label,value:e})}async setTitle(e){return m("plugin:window|set_title",{label:this.label,value:e})}async maximize(){return m("plugin:window|maximize",{label:this.label})}async unmaximize(){return m("plugin:window|unmaximize",{label:this.label})}async toggleMaximize(){return m("plugin:window|toggle_maximize",{label:this.label})}async minimize(){return m("plugin:window|minimize",{label:this.label})}async unminimize(){return m("plugin:window|unminimize",{label:this.label})}async show(){return m("plugin:window|show",{label:this.label})}async hide(){return m("plugin:window|hide",{label:this.label})}async close(){return m("plugin:window|close",{label:this.label})}async setDecorations(e){return m("plugin:window|set_decorations",{label:this.label,value:e})}async setShadow(e){return m("plugin:window|set_shadow",{label:this.label,value:e})}async setEffects(e){return m("plugin:window|set_effects",{label:this.label,value:e})}async clearEffects(){return m("plugin:window|set_effects",{label:this.label,value:null})}async setAlwaysOnTop(e){return m("plugin:window|set_always_on_top",{label:this.label,value:e})}async setAlwaysOnBottom(e){return m("plugin:window|set_always_on_bottom",{label:this.label,value:e})}async setContentProtected(e){return m("plugin:window|set_content_protected",{label:this.label,value:e})}async setSize(e){if(!e||e.type!=="Logical"&&e.type!=="Physical")throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return m("plugin:window|set_size",{label:this.label,value:{type:e.type,data:{width:e.width,height:e.height}}})}async setMinSize(e){if(e&&e.type!=="Logical"&&e.type!=="Physical")throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return m("plugin:window|set_min_size",{label:this.label,value:e?{type:e.type,data:{width:e.width,height:e.height}}:null})}async setMaxSize(e){if(e&&e.type!=="Logical"&&e.type!=="Physical")throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return m("plugin:window|set_max_size",{label:this.label,value:e?{type:e.type,data:{width:e.width,height:e.height}}:null})}async setPosition(e){if(!e||e.type!=="Logical"&&e.type!=="Physical")throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");return m("plugin:window|set_position",{label:this.label,value:{type:e.type,data:{x:e.x,y:e.y}}})}async setFullscreen(e){return m("plugin:window|set_fullscreen",{label:this.label,value:e})}async setFocus(){return m("plugin:window|set_focus",{label:this.label})}async setIcon(e){return m("plugin:window|set_icon",{label:this.label,value:typeof e=="string"?e:Array.from(e)})}async setSkipTaskbar(e){return m("plugin:window|set_skip_taskbar",{label:this.label,value:e})}async setCursorGrab(e){return m("plugin:window|set_cursor_grab",{label:this.label,value:e})}async setCursorVisible(e){return m("plugin:window|set_cursor_visible",{label:this.label,value:e})}async setCursorIcon(e){return m("plugin:window|set_cursor_icon",{label:this.label,value:e})}async setCursorPosition(e){if(!e||e.type!=="Logical"&&e.type!=="Physical")throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");return m("plugin:window|set_cursor_position",{label:this.label,value:{type:e.type,data:{x:e.x,y:e.y}}})}async setIgnoreCursorEvents(e){return m("plugin:window|set_ignore_cursor_events",{label:this.label,value:e})}async startDragging(){return m("plugin:window|start_dragging",{label:this.label})}async setProgressBar(e){return m("plugin:window|set_progress_bar",{label:this.label,value:e})}async onResized(e){return this.listen(Oe.WINDOW_RESIZED,n=>{n.payload=xr(n.payload),e(n)})}async onMoved(e){return this.listen(Oe.WINDOW_MOVED,n=>{n.payload=Al(n.payload),e(n)})}async onCloseRequested(e){return this.listen(Oe.WINDOW_CLOSE_REQUESTED,n=>{const l=new Zr(n);Promise.resolve(e(l)).then(()=>{if(!l.isPreventDefault())return this.close()})})}async onFocusChanged(e){const n=await this.listen(Oe.WINDOW_FOCUS,s=>{e({...s,payload:!0})}),l=await this.listen(Oe.WINDOW_BLUR,s=>{e({...s,payload:!1})});return()=>{n(),l()}}async onScaleChanged(e){return this.listen(Oe.WINDOW_SCALE_FACTOR_CHANGED,e)}async onFileDropEvent(e){const n=await this.listen(Oe.WINDOW_FILE_DROP,u=>{e({...u,payload:{type:"drop",paths:u.payload.paths,position:Al(u.payload.position)}})}),l=await this.listen(Oe.WINDOW_FILE_DROP_HOVER,u=>{e({...u,payload:{type:"hover",paths:u.payload.paths,position:Al(u.payload.position)}})}),s=await this.listen(Oe.WINDOW_FILE_DROP_CANCELLED,u=>{e({...u,payload:{type:"cancel"}})});return()=>{n(),l(),s()}}async onThemeChanged(e){return this.listen(Oe.WINDOW_THEME_CHANGED,e)}}var Ji;(function(t){t.AppearanceBased="appearanceBased",t.Light="light",t.Dark="dark",t.MediumLight="mediumLight",t.UltraDark="ultraDark",t.Titlebar="titlebar",t.Selection="selection",t.Menu="menu",t.Popover="popover",t.Sidebar="sidebar",t.HeaderView="headerView",t.Sheet="sheet",t.WindowBackground="windowBackground",t.HudWindow="hudWindow",t.FullScreenUI="fullScreenUI",t.Tooltip="tooltip",t.ContentBackground="contentBackground",t.UnderWindowBackground="underWindowBackground",t.UnderPageBackground="underPageBackground",t.Mica="mica",t.Blur="blur",t.Acrylic="acrylic",t.Tabbed="tabbed",t.TabbedDark="tabbedDark",t.TabbedLight="tabbedLight"})(Ji||(Ji={}));var Zi;(function(t){t.FollowsWindowActiveState="followsWindowActiveState",t.Active="active",t.Inactive="inactive"})(Zi||(Zi={}));function Al(t){return new it(t.x,t.y)}function xr(t){return new ln(t.width,t.height)}function Os(t,e,n){const l=t.slice();return l[105]=e[n],l}function Ws(t,e,n){const l=t.slice();return l[108]=e[n],l}function Is(t,e,n){const l=t.slice();return l[111]=e[n],l}function Rs(t,e,n){const l=t.slice();return l[114]=e[n],l}function Ds(t,e,n){const l=t.slice();return l[117]=e[n],l}function Fs(t){let e,n,l,s,u,d,o=fe(Object.keys(t[1])),c=[];for(let h=0;ht[59].call(l))},m(h,w){C(h,e,w),C(h,n,w),C(h,l,w),i(l,s);for(let _=0;_{n(2,u=o)}),Hr().then(o=>{n(0,l=o)}),Br().then(o=>{n(1,s=o)});function d(){m("popup_context_menu")}return[l,s,u,d]}class Gr extends xe{constructor(e){super(),Ze(this,e,jr,Nr,je,{})}}var Oe;(function(t){t.WINDOW_RESIZED="tauri://resize",t.WINDOW_MOVED="tauri://move",t.WINDOW_CLOSE_REQUESTED="tauri://close-requested",t.WINDOW_CREATED="tauri://window-created",t.WINDOW_DESTROYED="tauri://destroyed",t.WINDOW_FOCUS="tauri://focus",t.WINDOW_BLUR="tauri://blur",t.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",t.WINDOW_THEME_CHANGED="tauri://theme-changed",t.WINDOW_FILE_DROP="tauri://file-drop",t.WINDOW_FILE_DROP_HOVER="tauri://file-drop-hover",t.WINDOW_FILE_DROP_CANCELLED="tauri://file-drop-cancelled"})(Oe||(Oe={}));async function gr(t,e){await m("plugin:event|unlisten",{event:t,eventId:e})}async function Rl(t,e,n){return m("plugin:event|listen",{event:t,windowLabel:n==null?void 0:n.target,handler:pr(e)}).then(l=>async()=>gr(t,l))}async function Kr(t,e,n){return Rl(t,l=>{e(l),gr(t,l.id).catch(()=>{})},n)}async function _r(t,e,n){await m("plugin:event|emit",{event:t,windowLabel:n==null?void 0:n.target,payload:e})}function Xr(t){let e,n,l,s,u,d,o,c;return{c(){e=r("div"),n=r("button"),n.textContent="Call Log API",l=p(),s=r("button"),s.textContent="Call Request (async) API",u=p(),d=r("button"),d.textContent="Send event to Rust",a(n,"class","btn"),a(n,"id","log"),a(s,"class","btn"),a(s,"id","request"),a(d,"class","btn"),a(d,"id","event")},m(h,w){C(h,e,w),i(e,n),i(e,l),i(e,s),i(e,u),i(e,d),o||(c=[S(n,"click",t[0]),S(s,"click",t[1]),S(d,"click",t[2])],o=!0)},p:ie,i:ie,o:ie,d(h){h&&v(e),o=!1,Ce(c)}}}function Yr(t,e,n){let{onMessage:l}=e,s;Ki(async()=>{s=await Rl("rust-event",l)}),ar(()=>{s&&s()});function u(){m("log_operation",{event:"tauri-click",payload:"this payload is optional because we used Option in Rust"})}function d(){m("perform_request",{endpoint:"dummy endpoint arg",body:{id:5,name:"test"}}).then(l).catch(l)}function o(){_r("js-event","this is the payload string")}return t.$$set=c=>{"onMessage"in c&&n(3,l=c.onMessage)},[u,d,o,l]}class Qr extends xe{constructor(e){super(),Ze(this,e,Yr,Xr,je,{onMessage:3})}}class zl{constructor(e,n){this.type="Logical",this.width=e,this.height=n}}class sn{constructor(e,n){this.type="Physical",this.width=e,this.height=n}toLogical(e){return new zl(this.width/e,this.height/e)}}class Jr{constructor(e,n){this.type="Logical",this.x=e,this.y=n}}class it{constructor(e,n){this.type="Physical",this.x=e,this.y=n}toLogical(e){return new Jr(this.x/e,this.y/e)}}var Yi;(function(t){t[t.Critical=1]="Critical",t[t.Informational=2]="Informational"})(Yi||(Yi={}));class Zr{constructor(e){this._preventDefault=!1,this.event=e.event,this.windowLabel=e.windowLabel,this.id=e.id}preventDefault(){this._preventDefault=!0}isPreventDefault(){return this._preventDefault}}var Qi;(function(t){t.None="none",t.Normal="normal",t.Indeterminate="indeterminate",t.Paused="paused",t.Error="error"})(Qi||(Qi={}));function br(){return new Dn(window.__TAURI_INTERNALS__.metadata.currentWindow.label,{skip:!0})}function Ll(){return window.__TAURI_INTERNALS__.metadata.windows.map(t=>new Dn(t.label,{skip:!0}))}const zs=["tauri://created","tauri://error"];class Dn{constructor(e,n={}){this.label=e,this.listeners=Object.create(null),n!=null&&n.skip||m("plugin:window|create",{options:{...n,label:e}}).then(async()=>this.emit("tauri://created")).catch(async l=>this.emit("tauri://error",l))}static getByLabel(e){return Ll().some(n=>n.label===e)?new Dn(e,{skip:!0}):null}static getCurrent(){return br()}static getAll(){return Ll()}static async getFocusedWindow(){for(const e of Ll())if(await e.isFocused())return e;return null}async listen(e,n){return this._handleTauriEvent(e,n)?Promise.resolve(()=>{const l=this.listeners[e];l.splice(l.indexOf(n),1)}):Rl(e,n,{target:this.label})}async once(e,n){return this._handleTauriEvent(e,n)?Promise.resolve(()=>{const l=this.listeners[e];l.splice(l.indexOf(n),1)}):Kr(e,n,{target:this.label})}async emit(e,n){if(zs.includes(e)){for(const l of this.listeners[e]||[])l({event:e,id:-1,windowLabel:this.label,payload:n});return Promise.resolve()}return _r(e,n,{target:this.label})}_handleTauriEvent(e,n){return zs.includes(e)?(e in this.listeners?this.listeners[e].push(n):this.listeners[e]=[n],!0):!1}async scaleFactor(){return m("plugin:window|scale_factor",{label:this.label})}async innerPosition(){return m("plugin:window|inner_position",{label:this.label}).then(({x:e,y:n})=>new it(e,n))}async outerPosition(){return m("plugin:window|outer_position",{label:this.label}).then(({x:e,y:n})=>new it(e,n))}async innerSize(){return m("plugin:window|inner_size",{label:this.label}).then(({width:e,height:n})=>new sn(e,n))}async outerSize(){return m("plugin:window|outer_size",{label:this.label}).then(({width:e,height:n})=>new sn(e,n))}async isFullscreen(){return m("plugin:window|is_fullscreen",{label:this.label})}async isMinimized(){return m("plugin:window|is_minimized",{label:this.label})}async isMaximized(){return m("plugin:window|is_maximized",{label:this.label})}async isFocused(){return m("plugin:window|is_focused",{label:this.label})}async isDecorated(){return m("plugin:window|is_decorated",{label:this.label})}async isResizable(){return m("plugin:window|is_resizable",{label:this.label})}async isMaximizable(){return m("plugin:window|is_maximizable",{label:this.label})}async isMinimizable(){return m("plugin:window|is_minimizable",{label:this.label})}async isClosable(){return m("plugin:window|is_closable",{label:this.label})}async isVisible(){return m("plugin:window|is_visible",{label:this.label})}async title(){return m("plugin:window|title",{label:this.label})}async theme(){return m("plugin:window|theme",{label:this.label})}async center(){return m("plugin:window|center",{label:this.label})}async requestUserAttention(e){let n=null;return e&&(e===Yi.Critical?n={type:"Critical"}:n={type:"Informational"}),m("plugin:window|request_user_attention",{label:this.label,value:n})}async setResizable(e){return m("plugin:window|set_resizable",{label:this.label,value:e})}async setMaximizable(e){return m("plugin:window|set_maximizable",{label:this.label,value:e})}async setMinimizable(e){return m("plugin:window|set_minimizable",{label:this.label,value:e})}async setClosable(e){return m("plugin:window|set_closable",{label:this.label,value:e})}async setTitle(e){return m("plugin:window|set_title",{label:this.label,value:e})}async maximize(){return m("plugin:window|maximize",{label:this.label})}async unmaximize(){return m("plugin:window|unmaximize",{label:this.label})}async toggleMaximize(){return m("plugin:window|toggle_maximize",{label:this.label})}async minimize(){return m("plugin:window|minimize",{label:this.label})}async unminimize(){return m("plugin:window|unminimize",{label:this.label})}async show(){return m("plugin:window|show",{label:this.label})}async hide(){return m("plugin:window|hide",{label:this.label})}async close(){return m("plugin:window|close",{label:this.label})}async setDecorations(e){return m("plugin:window|set_decorations",{label:this.label,value:e})}async setShadow(e){return m("plugin:window|set_shadow",{label:this.label,value:e})}async setEffects(e){return m("plugin:window|set_effects",{label:this.label,value:e})}async clearEffects(){return m("plugin:window|set_effects",{label:this.label,value:null})}async setAlwaysOnTop(e){return m("plugin:window|set_always_on_top",{label:this.label,value:e})}async setAlwaysOnBottom(e){return m("plugin:window|set_always_on_bottom",{label:this.label,value:e})}async setContentProtected(e){return m("plugin:window|set_content_protected",{label:this.label,value:e})}async setSize(e){if(!e||e.type!=="Logical"&&e.type!=="Physical")throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return m("plugin:window|set_size",{label:this.label,value:{type:e.type,data:{width:e.width,height:e.height}}})}async setMinSize(e){if(e&&e.type!=="Logical"&&e.type!=="Physical")throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return m("plugin:window|set_min_size",{label:this.label,value:e?{type:e.type,data:{width:e.width,height:e.height}}:null})}async setMaxSize(e){if(e&&e.type!=="Logical"&&e.type!=="Physical")throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return m("plugin:window|set_max_size",{label:this.label,value:e?{type:e.type,data:{width:e.width,height:e.height}}:null})}async setPosition(e){if(!e||e.type!=="Logical"&&e.type!=="Physical")throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");return m("plugin:window|set_position",{label:this.label,value:{type:e.type,data:{x:e.x,y:e.y}}})}async setFullscreen(e){return m("plugin:window|set_fullscreen",{label:this.label,value:e})}async setFocus(){return m("plugin:window|set_focus",{label:this.label})}async setIcon(e){return m("plugin:window|set_icon",{label:this.label,value:typeof e=="string"?e:Array.from(e)})}async setSkipTaskbar(e){return m("plugin:window|set_skip_taskbar",{label:this.label,value:e})}async setCursorGrab(e){return m("plugin:window|set_cursor_grab",{label:this.label,value:e})}async setCursorVisible(e){return m("plugin:window|set_cursor_visible",{label:this.label,value:e})}async setCursorIcon(e){return m("plugin:window|set_cursor_icon",{label:this.label,value:e})}async setCursorPosition(e){if(!e||e.type!=="Logical"&&e.type!=="Physical")throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");return m("plugin:window|set_cursor_position",{label:this.label,value:{type:e.type,data:{x:e.x,y:e.y}}})}async setIgnoreCursorEvents(e){return m("plugin:window|set_ignore_cursor_events",{label:this.label,value:e})}async startDragging(){return m("plugin:window|start_dragging",{label:this.label})}async setProgressBar(e){return m("plugin:window|set_progress_bar",{label:this.label,value:e})}async onResized(e){return this.listen(Oe.WINDOW_RESIZED,n=>{n.payload=xr(n.payload),e(n)})}async onMoved(e){return this.listen(Oe.WINDOW_MOVED,n=>{n.payload=Al(n.payload),e(n)})}async onCloseRequested(e){return this.listen(Oe.WINDOW_CLOSE_REQUESTED,n=>{const l=new Zr(n);Promise.resolve(e(l)).then(()=>{if(!l.isPreventDefault())return this.close()})})}async onFocusChanged(e){const n=await this.listen(Oe.WINDOW_FOCUS,s=>{e({...s,payload:!0})}),l=await this.listen(Oe.WINDOW_BLUR,s=>{e({...s,payload:!1})});return()=>{n(),l()}}async onScaleChanged(e){return this.listen(Oe.WINDOW_SCALE_FACTOR_CHANGED,e)}async onFileDropEvent(e){const n=await this.listen(Oe.WINDOW_FILE_DROP,u=>{e({...u,payload:{type:"drop",paths:u.payload.paths,position:Al(u.payload.position)}})}),l=await this.listen(Oe.WINDOW_FILE_DROP_HOVER,u=>{e({...u,payload:{type:"hover",paths:u.payload.paths,position:Al(u.payload.position)}})}),s=await this.listen(Oe.WINDOW_FILE_DROP_CANCELLED,u=>{e({...u,payload:{type:"cancel"}})});return()=>{n(),l(),s()}}async onThemeChanged(e){return this.listen(Oe.WINDOW_THEME_CHANGED,e)}}var Ji;(function(t){t.AppearanceBased="appearanceBased",t.Light="light",t.Dark="dark",t.MediumLight="mediumLight",t.UltraDark="ultraDark",t.Titlebar="titlebar",t.Selection="selection",t.Menu="menu",t.Popover="popover",t.Sidebar="sidebar",t.HeaderView="headerView",t.Sheet="sheet",t.WindowBackground="windowBackground",t.HudWindow="hudWindow",t.FullScreenUI="fullScreenUI",t.Tooltip="tooltip",t.ContentBackground="contentBackground",t.UnderWindowBackground="underWindowBackground",t.UnderPageBackground="underPageBackground",t.Mica="mica",t.Blur="blur",t.Acrylic="acrylic",t.Tabbed="tabbed",t.TabbedDark="tabbedDark",t.TabbedLight="tabbedLight"})(Ji||(Ji={}));var Zi;(function(t){t.FollowsWindowActiveState="followsWindowActiveState",t.Active="active",t.Inactive="inactive"})(Zi||(Zi={}));function Al(t){return new it(t.x,t.y)}function xr(t){return new sn(t.width,t.height)}function Os(t,e,n){const l=t.slice();return l[105]=e[n],l}function Ws(t,e,n){const l=t.slice();return l[108]=e[n],l}function Is(t,e,n){const l=t.slice();return l[111]=e[n],l}function Rs(t,e,n){const l=t.slice();return l[114]=e[n],l}function Ds(t,e,n){const l=t.slice();return l[117]=e[n],l}function Fs(t){let e,n,l,s,u,d,o=fe(Object.keys(t[1])),c=[];for(let h=0;ht[59].call(l))},m(h,w){C(h,e,w),C(h,n,w),C(h,l,w),i(l,s);for(let _=0;_e in t?yr(t,e,{enumerable:!0,config `),ge=r("input"),_e=p(),Se=r("label"),Pe=b(`Content protected `),he=r("input"),Le=p(),oe=r("label"),Re=b(`Fullscreen `),De=r("input"),Ee=p(),ce=r("br"),F=p(),ee=r("div"),U=r("div"),Te=r("div"),Vn=b(`X - `),Fe=r("input"),qn=p(),Ot=r("div"),Nn=b(`Y - `),He=r("input"),jn=p(),lt=r("div"),Wt=r("div"),Gn=b(`Width - `),Ue=r("input"),Kn=p(),It=r("div"),Xn=b(`Height - `),Be=r("input"),Yn=p(),st=r("div"),Rt=r("div"),Qn=b(`Min width - `),Ge=r("input"),Jn=p(),Dt=r("div"),Zn=b(`Min height - `),Ke=r("input"),xn=p(),rt=r("div"),Ft=r("div"),$n=b(`Max width - `),Ve=r("input"),ei=p(),Ht=r("div"),ti=b(`Max height - `),qe=r("input"),hn=p(),fn=r("br"),pn=p(),ze=r("div"),at=r("div"),Xe=r("div"),N=r("div"),N.textContent="Inner Size",mn=p(),kt=r("span"),gn=b("Width: "),Ut=b(yt),_n=p(),vt=r("span"),bn=b("Height: "),Bt=b(Ct),wn=p(),Ne=r("div"),St=r("div"),St.textContent="Outer Size",kn=p(),Lt=r("span"),yn=b("Width: "),Vt=b(At),vn=p(),Mt=r("span"),Cn=b("Height: "),qt=b(Pt),ni=p(),Nt=r("div"),ut=r("div"),ii=r("div"),ii.textContent="Inner Logical Size",Fl=p(),li=r("span"),Hl=b("Width: "),xi=b(si),Ul=p(),ri=r("span"),Bl=b("Height: "),$i=b(ai),Vl=p(),ot=r("div"),ui=r("div"),ui.textContent="Outer Logical Size",ql=p(),oi=r("span"),Nl=b("Width: "),el=b(ci),jl=p(),di=r("span"),Gl=b("Height: "),tl=b(hi),Kl=p(),jt=r("div"),ct=r("div"),fi=r("div"),fi.textContent="Inner Position",Xl=p(),pi=r("span"),Yl=b("x: "),nl=b(mi),Ql=p(),gi=r("span"),Jl=b("y: "),il=b(_i),Zl=p(),dt=r("div"),bi=r("div"),bi.textContent="Outer Position",xl=p(),wi=r("span"),$l=b("x: "),ll=b(ki),es=p(),yi=r("span"),ts=b("y: "),sl=b(vi),ns=p(),Gt=r("div"),ht=r("div"),Ci=r("div"),Ci.textContent="Inner Logical Position",is=p(),Si=r("span"),ls=b("x: "),rl=b(Li),ss=p(),Ai=r("span"),rs=b("y: "),al=b(Mi),as=p(),ft=r("div"),Pi=r("div"),Pi.textContent="Outer Logical Position",us=p(),Ei=r("span"),os=b("x: "),ul=b(Ti),cs=p(),zi=r("span"),ds=b("y: "),ol=b(Oi),cl=p(),dl=r("br"),hl=p(),Sn=r("h4"),Sn.textContent="Cursor",fl=p(),$e=r("div"),Wi=r("label"),Kt=r("input"),hs=b(` - Grab`),fs=p(),Ii=r("label"),Xt=r("input"),ps=b(` - Visible`),ms=p(),Ri=r("label"),Yt=r("input"),gs=b(` + `),Fe=r("input"),qn=p(),Wt=r("div"),Nn=b(`Y + `),He=r("input"),jn=p(),lt=r("div"),It=r("div"),Gn=b(`Width + `),Ue=r("input"),Kn=p(),Rt=r("div"),Xn=b(`Height + `),Be=r("input"),Yn=p(),st=r("div"),Dt=r("div"),Qn=b(`Min width + `),Ge=r("input"),Jn=p(),Ft=r("div"),Zn=b(`Min height + `),Ke=r("input"),xn=p(),rt=r("div"),Ht=r("div"),$n=b(`Max width + `),Ve=r("input"),ei=p(),Ut=r("div"),ti=b(`Max height + `),qe=r("input"),fn=p(),pn=r("br"),mn=p(),ze=r("div"),at=r("div"),Xe=r("div"),N=r("div"),N.textContent="Inner Size",ut=p(),yt=r("span"),gn=b("Width: "),Bt=b(vt),_n=p(),Ct=r("span"),bn=b("Height: "),Vt=b(St),wn=p(),Ne=r("div"),Lt=r("div"),Lt.textContent="Outer Size",kn=p(),At=r("span"),yn=b("Width: "),qt=b(Mt),vn=p(),Pt=r("span"),Cn=b("Height: "),Nt=b(Et),ni=p(),jt=r("div"),ot=r("div"),ii=r("div"),ii.textContent="Inner Logical Size",Fl=p(),li=r("span"),Hl=b("Width: "),xi=b(si),Ul=p(),ri=r("span"),Bl=b("Height: "),$i=b(ai),Vl=p(),ct=r("div"),ui=r("div"),ui.textContent="Outer Logical Size",ql=p(),oi=r("span"),Nl=b("Width: "),el=b(ci),jl=p(),di=r("span"),Gl=b("Height: "),tl=b(hi),Kl=p(),Gt=r("div"),dt=r("div"),fi=r("div"),fi.textContent="Inner Position",Xl=p(),pi=r("span"),Yl=b("x: "),nl=b(mi),Ql=p(),gi=r("span"),Jl=b("y: "),il=b(_i),Zl=p(),ht=r("div"),bi=r("div"),bi.textContent="Outer Position",xl=p(),wi=r("span"),$l=b("x: "),ll=b(ki),es=p(),yi=r("span"),ts=b("y: "),sl=b(vi),ns=p(),Kt=r("div"),ft=r("div"),Ci=r("div"),Ci.textContent="Inner Logical Position",is=p(),Si=r("span"),ls=b("x: "),rl=b(Li),ss=p(),Ai=r("span"),rs=b("y: "),al=b(Mi),as=p(),pt=r("div"),Pi=r("div"),Pi.textContent="Outer Logical Position",us=p(),Ei=r("span"),os=b("x: "),ul=b(Ti),cs=p(),zi=r("span"),ds=b("y: "),ol=b(Oi),cl=p(),dl=r("br"),hl=p(),Sn=r("h4"),Sn.textContent="Cursor",fl=p(),$e=r("div"),Wi=r("label"),Xt=r("input"),hs=b(` + Grab`),fs=p(),Ii=r("label"),Yt=r("input"),ps=b(` + Visible`),ms=p(),Ri=r("label"),Qt=r("input"),gs=b(` Ignore events`),pl=p(),et=r("div"),Di=r("label"),_s=b(`Icon `),tt=r("select");for(let f=0;ft[83].call(tt)),a(pt,"class","input"),a(pt,"type","number"),a(mt,"class","input"),a(mt,"type","number"),a(et,"class","flex gap-2"),a(gt,"class","input grow"),a(gt,"id","title"),a(An,"class","btn"),a(An,"type","submit"),a(Et,"class","flex gap-1"),a(Ln,"class","flex flex-col gap-1"),a(nt,"class","input"),t[26]===void 0&&wt(()=>t[87].call(nt)),a(Ye,"class","input"),a(Ye,"type","number"),a(Ye,"min","0"),a(Ye,"max","100"),a(Qt,"class","flex gap-2"),a(Mn,"class","flex flex-col gap-1")},m(f,g){C(f,e,g),C(f,n,g),C(f,l,g),i(l,s),i(l,u),i(l,d),i(d,o),I(o,t[43]),i(d,c),i(d,h),C(f,w,g),C(f,_,g),C(f,A,g),C(f,k,g),i(k,y),i(k,L),i(k,M),i(k,B),i(k,D),i(k,O),i(k,P),C(f,E,g),C(f,z,g),i(z,R),i(R,J),i(R,V),V.checked=t[6],i(z,Z),i(z,le),i(le,te),i(le,q),q.checked=t[2],i(z,G),i(z,T),i(T,K),i(T,X),X.checked=t[3],i(z,be),i(z,ke),i(ke,de),i(ke,ae),ae.checked=t[4],i(z,$),i(z,pe),i(pe,Y),i(pe,se),se.checked=t[5],i(z,ne),i(z,W),i(W,x),i(W,H),H.checked=t[7],i(z,ue),i(z,Ae),i(Ae,we),i(Ae,me),me.checked=t[8],i(z,We),i(z,Me),i(Me,Ie),i(Me,ge),ge.checked=t[9],i(z,_e),i(z,Se),i(Se,Pe),i(Se,he),he.checked=t[10],i(z,Le),i(z,oe),i(oe,Re),i(oe,De),De.checked=t[11],C(f,Ee,g),C(f,ce,g),C(f,F,g),C(f,ee,g),i(ee,U),i(U,Te),i(Te,Vn),i(Te,Fe),I(Fe,t[18]),i(U,qn),i(U,Ot),i(Ot,Nn),i(Ot,He),I(He,t[19]),i(ee,jn),i(ee,lt),i(lt,Wt),i(Wt,Gn),i(Wt,Ue),I(Ue,t[12]),i(lt,Kn),i(lt,It),i(It,Xn),i(It,Be),I(Be,t[13]),i(ee,Yn),i(ee,st),i(st,Rt),i(Rt,Qn),i(Rt,Ge),I(Ge,t[14]),i(st,Jn),i(st,Dt),i(Dt,Zn),i(Dt,Ke),I(Ke,t[15]),i(ee,xn),i(ee,rt),i(rt,Ft),i(Ft,$n),i(Ft,Ve),I(Ve,t[16]),i(rt,ei),i(rt,Ht),i(Ht,ti),i(Ht,qe),I(qe,t[17]),C(f,hn,g),C(f,fn,g),C(f,pn,g),C(f,ze,g),i(ze,at),i(at,Xe),i(Xe,N),i(Xe,mn),i(Xe,kt),i(kt,gn),i(kt,Ut),i(Xe,_n),i(Xe,vt),i(vt,bn),i(vt,Bt),i(at,wn),i(at,Ne),i(Ne,St),i(Ne,kn),i(Ne,Lt),i(Lt,yn),i(Lt,Vt),i(Ne,vn),i(Ne,Mt),i(Mt,Cn),i(Mt,qt),i(ze,ni),i(ze,Nt),i(Nt,ut),i(ut,ii),i(ut,Fl),i(ut,li),i(li,Hl),i(li,xi),i(ut,Ul),i(ut,ri),i(ri,Bl),i(ri,$i),i(Nt,Vl),i(Nt,ot),i(ot,ui),i(ot,ql),i(ot,oi),i(oi,Nl),i(oi,el),i(ot,jl),i(ot,di),i(di,Gl),i(di,tl),i(ze,Kl),i(ze,jt),i(jt,ct),i(ct,fi),i(ct,Xl),i(ct,pi),i(pi,Yl),i(pi,nl),i(ct,Ql),i(ct,gi),i(gi,Jl),i(gi,il),i(jt,Zl),i(jt,dt),i(dt,bi),i(dt,xl),i(dt,wi),i(wi,$l),i(wi,ll),i(dt,es),i(dt,yi),i(yi,ts),i(yi,sl),i(ze,ns),i(ze,Gt),i(Gt,ht),i(ht,Ci),i(ht,is),i(ht,Si),i(Si,ls),i(Si,rl),i(ht,ss),i(ht,Ai),i(Ai,rs),i(Ai,al),i(Gt,as),i(Gt,ft),i(ft,Pi),i(ft,us),i(ft,Ei),i(Ei,os),i(Ei,ul),i(ft,cs),i(ft,zi),i(zi,ds),i(zi,ol),C(f,cl,g),C(f,dl,g),C(f,hl,g),C(f,Sn,g),C(f,fl,g),C(f,$e,g),i($e,Wi),i(Wi,Kt),Kt.checked=t[20],i(Wi,hs),i($e,fs),i($e,Ii),i(Ii,Xt),Xt.checked=t[21],i(Ii,ps),i($e,ms),i($e,Ri),i(Ri,Yt),Yt.checked=t[25],i(Ri,gs),C(f,pl,g),C(f,et,g),i(et,Di),i(Di,_s),i(Di,tt);for(let j=0;jt[83].call(tt)),a(mt,"class","input"),a(mt,"type","number"),a(gt,"class","input"),a(gt,"type","number"),a(et,"class","flex gap-2"),a(_t,"class","input grow"),a(_t,"id","title"),a(An,"class","btn"),a(An,"type","submit"),a(Tt,"class","flex gap-1"),a(Ln,"class","flex flex-col gap-1"),a(nt,"class","input"),t[26]===void 0&&kt(()=>t[87].call(nt)),a(Ye,"class","input"),a(Ye,"type","number"),a(Ye,"min","0"),a(Ye,"max","100"),a(Jt,"class","flex gap-2"),a(Mn,"class","flex flex-col gap-1")},m(f,g){C(f,e,g),C(f,n,g),C(f,l,g),i(l,s),i(l,u),i(l,d),i(d,o),I(o,t[43]),i(d,c),i(d,h),C(f,w,g),C(f,_,g),C(f,A,g),C(f,k,g),i(k,y),i(k,L),i(k,M),i(k,B),i(k,D),i(k,O),i(k,P),C(f,E,g),C(f,z,g),i(z,R),i(R,J),i(R,V),V.checked=t[6],i(z,Z),i(z,le),i(le,te),i(le,q),q.checked=t[2],i(z,G),i(z,T),i(T,K),i(T,X),X.checked=t[3],i(z,be),i(z,ke),i(ke,de),i(ke,ae),ae.checked=t[4],i(z,$),i(z,pe),i(pe,Y),i(pe,se),se.checked=t[5],i(z,ne),i(z,W),i(W,x),i(W,H),H.checked=t[7],i(z,ue),i(z,Ae),i(Ae,we),i(Ae,me),me.checked=t[8],i(z,We),i(z,Me),i(Me,Ie),i(Me,ge),ge.checked=t[9],i(z,_e),i(z,Se),i(Se,Pe),i(Se,he),he.checked=t[10],i(z,Le),i(z,oe),i(oe,Re),i(oe,De),De.checked=t[11],C(f,Ee,g),C(f,ce,g),C(f,F,g),C(f,ee,g),i(ee,U),i(U,Te),i(Te,Vn),i(Te,Fe),I(Fe,t[18]),i(U,qn),i(U,Wt),i(Wt,Nn),i(Wt,He),I(He,t[19]),i(ee,jn),i(ee,lt),i(lt,It),i(It,Gn),i(It,Ue),I(Ue,t[12]),i(lt,Kn),i(lt,Rt),i(Rt,Xn),i(Rt,Be),I(Be,t[13]),i(ee,Yn),i(ee,st),i(st,Dt),i(Dt,Qn),i(Dt,Ge),I(Ge,t[14]),i(st,Jn),i(st,Ft),i(Ft,Zn),i(Ft,Ke),I(Ke,t[15]),i(ee,xn),i(ee,rt),i(rt,Ht),i(Ht,$n),i(Ht,Ve),I(Ve,t[16]),i(rt,ei),i(rt,Ut),i(Ut,ti),i(Ut,qe),I(qe,t[17]),C(f,fn,g),C(f,pn,g),C(f,mn,g),C(f,ze,g),i(ze,at),i(at,Xe),i(Xe,N),i(Xe,ut),i(Xe,yt),i(yt,gn),i(yt,Bt),i(Xe,_n),i(Xe,Ct),i(Ct,bn),i(Ct,Vt),i(at,wn),i(at,Ne),i(Ne,Lt),i(Ne,kn),i(Ne,At),i(At,yn),i(At,qt),i(Ne,vn),i(Ne,Pt),i(Pt,Cn),i(Pt,Nt),i(ze,ni),i(ze,jt),i(jt,ot),i(ot,ii),i(ot,Fl),i(ot,li),i(li,Hl),i(li,xi),i(ot,Ul),i(ot,ri),i(ri,Bl),i(ri,$i),i(jt,Vl),i(jt,ct),i(ct,ui),i(ct,ql),i(ct,oi),i(oi,Nl),i(oi,el),i(ct,jl),i(ct,di),i(di,Gl),i(di,tl),i(ze,Kl),i(ze,Gt),i(Gt,dt),i(dt,fi),i(dt,Xl),i(dt,pi),i(pi,Yl),i(pi,nl),i(dt,Ql),i(dt,gi),i(gi,Jl),i(gi,il),i(Gt,Zl),i(Gt,ht),i(ht,bi),i(ht,xl),i(ht,wi),i(wi,$l),i(wi,ll),i(ht,es),i(ht,yi),i(yi,ts),i(yi,sl),i(ze,ns),i(ze,Kt),i(Kt,ft),i(ft,Ci),i(ft,is),i(ft,Si),i(Si,ls),i(Si,rl),i(ft,ss),i(ft,Ai),i(Ai,rs),i(Ai,al),i(Kt,as),i(Kt,pt),i(pt,Pi),i(pt,us),i(pt,Ei),i(Ei,os),i(Ei,ul),i(pt,cs),i(pt,zi),i(zi,ds),i(zi,ol),C(f,cl,g),C(f,dl,g),C(f,hl,g),C(f,Sn,g),C(f,fl,g),C(f,$e,g),i($e,Wi),i(Wi,Xt),Xt.checked=t[20],i(Wi,hs),i($e,fs),i($e,Ii),i(Ii,Yt),Yt.checked=t[21],i(Ii,ps),i($e,ms),i($e,Ri),i(Ri,Qt),Qt.checked=t[25],i(Ri,gs),C(f,pl,g),C(f,et,g),i(et,Di),i(Di,_s),i(Di,tt);for(let j=0;jt[89].call(u)),a(h,"class","input"),t[37]===void 0&&wt(()=>t[90].call(h)),a(k,"class","input"),a(k,"type","number"),a(n,"class","flex"),xt(O,"max-width","120px"),a(O,"class","input"),a(O,"type","number"),a(O,"placeholder","R"),xt(E,"max-width","120px"),a(E,"class","input"),a(E,"type","number"),a(E,"placeholder","G"),xt(R,"max-width","120px"),a(R,"class","input"),a(R,"type","number"),a(R,"placeholder","B"),xt(V,"max-width","120px"),a(V,"class","input"),a(V,"type","number"),a(V,"placeholder","A"),a(D,"class","flex"),a(L,"class","flex"),a(te,"class","btn"),xt(te,"width","80px"),a(le,"class","flex"),a(de,"class","btn"),xt(de,"width","80px"),a(G,"class","flex"),a(e,"class","flex flex-col gap-1")},m(W,x){C(W,e,x),i(e,n),i(n,l),i(l,s),i(l,u);for(let H=0;H=1,w,_,A,k=h&&Fs(t),y=t[1][t[0]]&&Us(t);return{c(){e=r("div"),n=r("div"),l=r("input"),s=p(),u=r("button"),u.textContent="New window",d=p(),o=r("br"),c=p(),k&&k.c(),w=p(),y&&y.c(),a(l,"class","input grow"),a(l,"type","text"),a(l,"placeholder","New Window label.."),a(u,"class","btn"),a(n,"class","flex gap-1"),a(e,"class","flex flex-col children:grow gap-2")},m(L,M){C(L,e,M),i(e,n),i(n,l),I(l,t[28]),i(n,s),i(n,u),i(e,d),i(e,o),i(e,c),k&&k.m(e,null),i(e,w),y&&y.m(e,null),_||(A=[S(l,"input",t[58]),S(u,"click",t[53])],_=!0)},p(L,M){M[0]&268435456&&l.value!==L[28]&&I(l,L[28]),M[0]&2&&(h=Object.keys(L[1]).length>=1),h?k?k.p(L,M):(k=Fs(L),k.c(),k.m(e,w)):k&&(k.d(1),k=null),L[1][L[0]]?y?y.p(L,M):(y=Us(L),y.c(),y.m(e,null)):y&&(y.d(1),y=null)},i:ie,o:ie,d(L){L&&v(e),k&&k.d(),y&&y.d(),_=!1,Ce(A)}}}function ta(t,e,n){const l=br();let s=l.label;const u={[l.label]:l},d=["default","crosshair","hand","arrow","move","text","wait","help","progress","notAllowed","contextMenu","cell","verticalText","alias","copy","noDrop","grab","grabbing","allScroll","zoomIn","zoomOut","eResize","nResize","neResize","nwResize","sResize","seResize","swResize","wResize","ewResize","nsResize","neswResize","nwseResize","colResize","rowResize"],o=["mica","blur","acrylic","tabbed","tabbedDark","tabbedLight"],c=navigator.appVersion.includes("Windows"),h=navigator.appVersion.includes("Macintosh");let w=c?o:Object.keys(Ji).map(N=>Ji[N]).filter(N=>!o.includes(N));const _=Object.keys(Zi).map(N=>Zi[N]),A=Object.keys(Qi).map(N=>Qi[N]);let{onMessage:k}=e;const y=document.querySelector("main");let L,M=!0,B=!0,D=!0,O=!0,P=!1,E=!0,z=!1,R=!1,J=!0,V=!1,Z=null,le=null,te=null,q=null,G=null,T=null,K=null,X=null,be=1,ke=new it(K,X),de=new it(K,X),ae=new ln(Z,le),$=new ln(Z,le),pe,Y,se=!1,ne=!0,W=null,x=null,H="default",ue=!1,Ae="Awesome Tauri Example!",we=[],me,We,Me,Ie,ge,_e,Se,Pe="none",he=0,Le;function oe(){u[s].setTitle(Ae)}function Re(){u[s].hide(),setTimeout(u[s].show,2e3)}function De(){u[s].minimize(),setTimeout(u[s].unminimize,2e3)}function Ee(){if(!L)return;const N=new Dn(L);n(1,u[L]=N,u),N.once("tauri://error",function(){k("Error creating new webview")})}function ce(){u[s].innerSize().then(N=>{n(32,ae=N),n(12,Z=ae.width),n(13,le=ae.height)}),u[s].outerSize().then(N=>{n(33,$=N)})}function F(){u[s].innerPosition().then(N=>{n(30,ke=N)}),u[s].outerPosition().then(N=>{n(31,de=N),n(18,K=de.x),n(19,X=de.y)})}async function ee(N){N&&(pe&&pe(),Y&&Y(),Y=await N.listen("tauri://move",F),pe=await N.listen("tauri://resize",ce))}async function U(){await u[s].minimize(),await u[s].requestUserAttention(Yi.Critical),await new Promise(N=>setTimeout(N,3e3)),await u[s].requestUserAttention(null)}async function Te(){we.includes(me)||n(35,we=[...we,me]);const N={effects:we,state:We,radius:Me};Number.isInteger(Ie)&&Number.isInteger(ge)&&Number.isInteger(_e)&&Number.isInteger(Se)&&(N.color=[Ie,ge,_e,Se]),y.classList.remove("bg-primary"),y.classList.remove("dark:bg-darkPrimary"),await u[s].clearEffects(),await u[s].setEffects(N)}async function Vn(){n(35,we=[]),await u[s].clearEffects(),y.classList.add("bg-primary"),y.classList.add("dark:bg-darkPrimary")}function Fe(){L=this.value,n(28,L)}function qn(){s=En(this),n(0,s),n(1,u)}function Ot(){Le=this.value,n(43,Le)}const Nn=()=>u[s].center();function He(){P=this.checked,n(6,P)}function jn(){M=this.checked,n(2,M)}function lt(){B=this.checked,n(3,B)}function Wt(){D=this.checked,n(4,D)}function Gn(){O=this.checked,n(5,O)}function Ue(){E=this.checked,n(7,E)}function Kn(){z=this.checked,n(8,z)}function It(){R=this.checked,n(9,R)}function Xn(){J=this.checked,n(10,J)}function Be(){V=this.checked,n(11,V)}function Yn(){K=Q(this.value),n(18,K)}function st(){X=Q(this.value),n(19,X)}function Rt(){Z=Q(this.value),n(12,Z)}function Qn(){le=Q(this.value),n(13,le)}function Ge(){te=Q(this.value),n(14,te)}function Jn(){q=Q(this.value),n(15,q)}function Dt(){G=Q(this.value),n(16,G)}function Zn(){T=Q(this.value),n(17,T)}function Ke(){se=this.checked,n(20,se)}function xn(){ne=this.checked,n(21,ne)}function rt(){ue=this.checked,n(25,ue)}function Ft(){H=En(this),n(24,H),n(44,d)}function $n(){W=Q(this.value),n(22,W)}function Ve(){x=Q(this.value),n(23,x)}function ei(){Ae=this.value,n(34,Ae)}function Ht(){Pe=En(this),n(26,Pe),n(49,A)}function ti(){he=Q(this.value),n(27,he)}function qe(){me=En(this),n(36,me),n(47,w)}function hn(){We=En(this),n(37,We),n(48,_)}function fn(){Me=Q(this.value),n(38,Me)}function pn(){Ie=Q(this.value),n(39,Ie)}function ze(){ge=Q(this.value),n(40,ge)}function at(){_e=Q(this.value),n(41,_e)}function Xe(){Se=Q(this.value),n(42,Se)}return t.$$set=N=>{"onMessage"in N&&n(57,k=N.onMessage)},t.$$.update=()=>{var N,mn,kt,gn,yt,Ut,_n,vt,bn,Ct,Bt,wn,Ne,St,kn,Lt,yn,At,Vt,vn,Mt,Cn,Pt,qt;t.$$.dirty[0]&3&&(u[s],F(),ce()),t.$$.dirty[0]&7&&((N=u[s])==null||N.setResizable(M)),t.$$.dirty[0]&11&&((mn=u[s])==null||mn.setMaximizable(B)),t.$$.dirty[0]&19&&((kt=u[s])==null||kt.setMinimizable(D)),t.$$.dirty[0]&35&&((gn=u[s])==null||gn.setClosable(O)),t.$$.dirty[0]&67&&(P?(yt=u[s])==null||yt.maximize():(Ut=u[s])==null||Ut.unmaximize()),t.$$.dirty[0]&131&&((_n=u[s])==null||_n.setDecorations(E)),t.$$.dirty[0]&259&&((vt=u[s])==null||vt.setAlwaysOnTop(z)),t.$$.dirty[0]&515&&((bn=u[s])==null||bn.setAlwaysOnBottom(R)),t.$$.dirty[0]&1027&&((Ct=u[s])==null||Ct.setContentProtected(J)),t.$$.dirty[0]&2051&&((Bt=u[s])==null||Bt.setFullscreen(V)),t.$$.dirty[0]&12291&&Z&&le&&((wn=u[s])==null||wn.setSize(new ln(Z,le))),t.$$.dirty[0]&49155&&(te&&q?(Ne=u[s])==null||Ne.setMinSize(new zl(te,q)):(St=u[s])==null||St.setMinSize(null)),t.$$.dirty[0]&196611&&(G>800&&T>400?(kn=u[s])==null||kn.setMaxSize(new zl(G,T)):(Lt=u[s])==null||Lt.setMaxSize(null)),t.$$.dirty[0]&786435&&K!==null&&X!==null&&((yn=u[s])==null||yn.setPosition(new it(K,X))),t.$$.dirty[0]&3&&((At=u[s])==null||At.scaleFactor().then(ni=>n(29,be=ni))),t.$$.dirty[0]&3&&ee(u[s]),t.$$.dirty[0]&1048579&&((Vt=u[s])==null||Vt.setCursorGrab(se)),t.$$.dirty[0]&2097155&&((vn=u[s])==null||vn.setCursorVisible(ne)),t.$$.dirty[0]&16777219&&((Mt=u[s])==null||Mt.setCursorIcon(H)),t.$$.dirty[0]&12582915&&W!==null&&x!==null&&((Cn=u[s])==null||Cn.setCursorPosition(new it(W,x))),t.$$.dirty[0]&33554435&&((Pt=u[s])==null||Pt.setIgnoreCursorEvents(ue)),t.$$.dirty[0]&201326595&&((qt=u[s])==null||qt.setProgressBar({status:Pe,progress:he}))},[s,u,M,B,D,O,P,E,z,R,J,V,Z,le,te,q,G,T,K,X,se,ne,W,x,H,ue,Pe,he,L,be,ke,de,ae,$,Ae,we,me,We,Me,Ie,ge,_e,Se,Le,d,c,h,w,_,A,oe,Re,De,Ee,U,Te,Vn,k,Fe,qn,Ot,Nn,He,jn,lt,Wt,Gn,Ue,Kn,It,Xn,Be,Yn,st,Rt,Qn,Ge,Jn,Dt,Zn,Ke,xn,rt,Ft,$n,Ve,ei,Ht,ti,qe,hn,fn,pn,ze,at,Xe]}class na extends xe{constructor(e){super(),Ze(this,e,ta,ea,je,{onMessage:57},null,[-1,-1,-1,-1])}}function ia(t){let e;return{c(){e=r("div"),e.innerHTML='
Not available for Linux
',a(e,"class","flex flex-col gap-2")},m(n,l){C(n,e,l)},p:ie,i:ie,o:ie,d(n){n&&v(e)}}}function la(t,e,n){let{onMessage:l}=e;const s=window.constraints={audio:!0,video:!0};function u(o){const c=document.querySelector("video"),h=o.getVideoTracks();l("Got stream with constraints:",s),l(`Using video device: ${h[0].label}`),window.stream=o,c.srcObject=o}function d(o){if(o.name==="ConstraintNotSatisfiedError"){const c=s.video;l(`The resolution ${c.width.exact}x${c.height.exact} px is not supported by your device.`)}else o.name==="PermissionDeniedError"&&l("Permissions have not been granted to use your camera and microphone, you need to allow the page access to your devices in order for the demo to work.");l(`getUserMedia error: ${o.name}`,o)}return Ki(async()=>{try{const o=await navigator.mediaDevices.getUserMedia(s);u(o)}catch(o){d(o)}}),ar(()=>{var o;(o=window.stream)==null||o.getTracks().forEach(function(c){c.stop()})}),t.$$set=o=>{"onMessage"in o&&n(0,l=o.onMessage)},[l]}class sa extends xe{constructor(e){super(),Ze(this,e,la,ia,je,{onMessage:0})}}function ra(t){let e,n,l,s,u,d;return{c(){e=r("div"),n=r("button"),n.textContent="Show",l=p(),s=r("button"),s.textContent="Hide",a(n,"class","btn"),a(n,"id","show"),a(n,"title","Hides and shows the app after 2 seconds"),a(s,"class","btn"),a(s,"id","hide")},m(o,c){C(o,e,c),i(e,n),i(e,l),i(e,s),u||(d=[S(n,"click",t[0]),S(s,"click",t[1])],u=!0)},p:ie,i:ie,o:ie,d(o){o&&v(e),u=!1,Ce(d)}}}function aa(t,e,n){let{onMessage:l}=e;function s(){u().then(()=>{setTimeout(()=>{Vr().then(()=>l("Shown app")).catch(l)},2e3)}).catch(l)}function u(){return qr().then(()=>l("Hide app")).catch(l)}return t.$$set=d=>{"onMessage"in d&&n(2,l=d.onMessage)},[s,u,l]}class ua extends xe{constructor(e){super(),Ze(this,e,aa,ra,je,{onMessage:2})}}var ji,Gi;function wr(t){var e;if("items"in t)t.items=(e=t.items)==null?void 0:e.map(n=>"rid"in n?n:wr(n));else if("action"in t&&t.action){const n=new Il;return n.onmessage=t.action,delete t.action,{...t,handler:n}}return t}async function on(t,e){const n=new Il;let l=null;return e&&typeof e=="object"&&("action"in e&&e.action&&(n.onmessage=e.action,delete e.action),"items"in e&&e.items&&(l=e.items.map(s=>"rid"in s?[s.rid,s.kind]:wr(s)))),m("plugin:menu|new",{kind:t,options:e?{...e,items:l}:void 0,handler:n})}class cn extends mr{get id(){return Rn(this,ji,"f")}get kind(){return Rn(this,Gi,"f")}constructor(e,n,l){super(e),ji.set(this,void 0),Gi.set(this,void 0),Xi(this,ji,n,"f"),Xi(this,Gi,l,"f")}}ji=new WeakMap,Gi=new WeakMap;class Fn extends cn{constructor(e,n){super(e,n,"MenuItem")}static async new(e){return on("MenuItem",e).then(([n,l])=>new Fn(n,l))}async text(){return m("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return m("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return m("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return m("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return m("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}}class dn extends cn{constructor(e,n){super(e,n,"Check")}static async new(e){return on("Check",e).then(([n,l])=>new dn(n,l))}async text(){return m("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return m("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return m("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return m("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return m("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}async isChecked(){return m("plugin:menu|is_checked",{rid:this.rid})}async setChecked(e){return m("plugin:menu|set_checked",{rid:this.rid,checked:e})}}var js;(function(t){t.Add="Add",t.Advanced="Advanced",t.Bluetooth="Bluetooth",t.Bookmarks="Bookmarks",t.Caution="Caution",t.ColorPanel="ColorPanel",t.ColumnView="ColumnView",t.Computer="Computer",t.EnterFullScreen="EnterFullScreen",t.Everyone="Everyone",t.ExitFullScreen="ExitFullScreen",t.FlowView="FlowView",t.Folder="Folder",t.FolderBurnable="FolderBurnable",t.FolderSmart="FolderSmart",t.FollowLinkFreestanding="FollowLinkFreestanding",t.FontPanel="FontPanel",t.GoLeft="GoLeft",t.GoRight="GoRight",t.Home="Home",t.IChatTheater="IChatTheater",t.IconView="IconView",t.Info="Info",t.InvalidDataFreestanding="InvalidDataFreestanding",t.LeftFacingTriangle="LeftFacingTriangle",t.ListView="ListView",t.LockLocked="LockLocked",t.LockUnlocked="LockUnlocked",t.MenuMixedState="MenuMixedState",t.MenuOnState="MenuOnState",t.MobileMe="MobileMe",t.MultipleDocuments="MultipleDocuments",t.Network="Network",t.Path="Path",t.PreferencesGeneral="PreferencesGeneral",t.QuickLook="QuickLook",t.RefreshFreestanding="RefreshFreestanding",t.Refresh="Refresh",t.Remove="Remove",t.RevealFreestanding="RevealFreestanding",t.RightFacingTriangle="RightFacingTriangle",t.Share="Share",t.Slideshow="Slideshow",t.SmartBadge="SmartBadge",t.StatusAvailable="StatusAvailable",t.StatusNone="StatusNone",t.StatusPartiallyAvailable="StatusPartiallyAvailable",t.StatusUnavailable="StatusUnavailable",t.StopProgressFreestanding="StopProgressFreestanding",t.StopProgress="StopProgress",t.TrashEmpty="TrashEmpty",t.TrashFull="TrashFull",t.User="User",t.UserAccounts="UserAccounts",t.UserGroup="UserGroup",t.UserGuest="UserGuest"})(js||(js={}));class Hn extends cn{constructor(e,n){super(e,n,"Icon")}static async new(e){return on("Icon",e).then(([n,l])=>new Hn(n,l))}async text(){return m("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return m("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return m("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return m("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return m("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}async setIcon(e){return m("plugin:menu|set_icon",{rid:this.rid,icon:e})}}class Un extends cn{constructor(e,n){super(e,n,"Predefined")}static async new(e){return on("Predefined",e).then(([n,l])=>new Un(n,l))}async text(){return m("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return m("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}}function Ml([t,e,n]){switch(n){case"Submenu":return new Bn(t,e);case"Predefined":return new Un(t,e);case"Check":return new dn(t,e);case"Icon":return new Hn(t,e);case"MenuItem":default:return new Fn(t,e)}}class Bn extends cn{constructor(e,n){super(e,n,"Submenu")}static async new(e){return on("Submenu",e).then(([n,l])=>new Bn(n,l))}async text(){return m("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return m("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return m("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return m("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async append(e){return m("plugin:menu|append",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map(n=>"rid"in n?[n.rid,n.kind]:n)})}async prepend(e){return m("plugin:menu|prepend",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map(n=>"rid"in n?[n.rid,n.kind]:n)})}async insert(e,n){return m("plugin:menu|insert",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map(l=>"rid"in l?[l.rid,l.kind]:l),position:n})}async remove(e){return m("plugin:menu|remove",{rid:this.rid,kind:this.kind,item:[e.rid,e.kind]})}async removeAt(e){return m("plugin:menu|remove_at",{rid:this.rid,kind:this.kind,position:e}).then(Ml)}async items(){return m("plugin:menu|items",{rid:this.rid,kind:this.kind}).then(e=>e.map(Ml))}async get(e){return m("plugin:menu|get",{rid:this.rid,kind:this.kind,id:e}).then(n=>n?Ml(n):null)}async popup(e,n){let l=null;return e&&(l={type:e instanceof it?"Physical":"Logical",data:e}),m("plugin:menu|popup",{rid:this.rid,kind:this.kind,window:(n==null?void 0:n.label)??null,at:l})}async setAsWindowsMenuForNSApp(){return m("plugin:menu|set_as_windows_menu_for_nsapp",{rid:this.rid})}async setAsHelpMenuForNSApp(){return m("plugin:menu|set_as_help_menu_for_nsapp",{rid:this.rid})}}function Pl([t,e,n]){switch(n){case"Submenu":return new Bn(t,e);case"Predefined":return new Un(t,e);case"Check":return new dn(t,e);case"Icon":return new Hn(t,e);case"MenuItem":default:return new Fn(t,e)}}class bt extends cn{constructor(e,n){super(e,n,"Menu")}static async new(e){return on("Menu",e).then(([n,l])=>new bt(n,l))}static async default(){return m("plugin:menu|default").then(([e,n])=>new bt(e,n))}async append(e){return m("plugin:menu|append",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map(n=>"rid"in n?[n.rid,n.kind]:n)})}async prepend(e){return m("plugin:menu|prepend",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map(n=>"rid"in n?[n.rid,n.kind]:n)})}async insert(e,n){return m("plugin:menu|insert",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map(l=>"rid"in l?[l.rid,l.kind]:l),position:n})}async remove(e){return m("plugin:menu|remove",{rid:this.rid,kind:this.kind,item:[e.rid,e.kind]})}async removeAt(e){return m("plugin:menu|remove_at",{rid:this.rid,kind:this.kind,position:e}).then(Pl)}async items(){return m("plugin:menu|items",{rid:this.rid,kind:this.kind}).then(e=>e.map(Pl))}async get(e){return m("plugin:menu|get",{rid:this.rid,kind:this.kind,id:e}).then(n=>n?Pl(n):null)}async popup(e,n){let l=null;return e&&(l={type:e instanceof it?"Physical":"Logical",data:e}),m("plugin:menu|popup",{rid:this.rid,kind:this.kind,window:(n==null?void 0:n.label)??null,at:l})}async setAsAppMenu(){return m("plugin:menu|set_as_app_menu",{rid:this.rid}).then(e=>e?new bt(e[0],e[1]):null)}async setAsWindowMenu(e){return m("plugin:menu|set_as_window_menu",{rid:this.rid,window:(e==null?void 0:e.label)??null}).then(n=>n?new bt(n[0],n[1]):null)}}function Gs(t,e,n){const l=t.slice();return l[16]=e[n],l[17]=e,l[18]=n,l}function Ks(t,e,n){const l=t.slice();return l[19]=e[n],l[20]=e,l[21]=n,l}function Xs(t){let e,n,l,s,u,d,o=t[19]+"",c,h,w,_,A;function k(){t[9].call(n,t[20],t[21])}return{c(){e=r("div"),n=r("input"),u=p(),d=r("label"),c=b(o),w=p(),a(n,"id",l=t[19]+"Input"),n.checked=s=t[0]===t[19],a(n,"type","radio"),a(n,"name","kind"),a(d,"for",h=t[19]+"Input"),a(e,"class","flex gap-1")},m(y,L){C(y,e,L),i(e,n),I(n,t[19]),i(e,u),i(e,d),i(d,c),i(e,w),_||(A=[S(n,"change",t[6]),S(n,"change",k)],_=!0)},p(y,L){t=y,L&16&&l!==(l=t[19]+"Input")&&a(n,"id",l),L&17&&s!==(s=t[0]===t[19])&&(n.checked=s),L&16&&I(n,t[19]),L&16&&o!==(o=t[19]+"")&&re(c,o),L&16&&h!==(h=t[19]+"Input")&&a(d,"for",h)},d(y){y&&v(e),_=!1,Ce(A)}}}function Ys(t){let e,n,l;return{c(){e=r("input"),a(e,"class","input"),a(e,"type","text"),a(e,"placeholder","Text")},m(s,u){C(s,e,u),I(e,t[1]),n||(l=S(e,"input",t[10]),n=!0)},p(s,u){u&2&&e.value!==s[1]&&I(e,s[1])},d(s){s&&v(e),n=!1,l()}}}function oa(t){let e,n=fe(t[5]),l=[];for(let s=0;sl("itemClick",{id:z,text:E})},P=await Fn.new(O);break;case"Icon":O={text:u,icon:d,action:z=>l("itemClick",{id:z,text:E})},P=await Hn.new(O);break;case"Check":O={text:u,checked:c,action:z=>l("itemClick",{id:z,text:E})},P=await dn.new(O);break;case"Predefined":O={item:o},P=await Un.new(O);break}l("new",{item:P,options:O}),n(1,u=""),o=""}function y(O,P){O[P]=this.value,n(4,h)}function L(){u=this.value,n(1,u)}function M(){d=this.value,n(2,d)}function B(){c=this.checked,n(3,c)}function D(O,P){O[P]=this.value,n(5,w)}return[s,u,d,c,h,w,_,A,k,y,L,M,B,D]}class pa extends xe{constructor(e){super(),Ze(this,e,fa,ha,je,{})}}function Js(t,e,n){const l=t.slice();return l[5]=e[n],l}function Zs(t){let e,n,l,s,u,d=xs(t[5])+"",o,c;return{c(){e=r("div"),n=r("div"),s=p(),u=r("p"),o=b(d),c=p(),a(n,"class",l=t[3](t[5])),a(e,"class","flex flex-row gap-1")},m(h,w){C(h,e,w),i(e,n),i(e,s),i(e,u),i(u,o),i(e,c)},p(h,w){w&1&&l!==(l=h[3](h[5]))&&a(n,"class",l),w&1&&d!==(d=xs(h[5])+"")&&re(o,d)},d(h){h&&v(e)}}}function ma(t){let e,n,l,s,u;n=new pa({}),n.$on("new",t[1]),n.$on("itemClick",t[2]);let d=fe(t[0]),o=[];for(let c=0;c{"items"in c&&n(0,l=c.items)},[l,u,d,o]}class kr extends xe{constructor(e){super(),Ze(this,e,ga,ma,je,{items:0})}}function _a(t){let e,n,l,s,u,d,o,c,h,w;function _(k){t[5](k)}let A={};return t[0]!==void 0&&(A.items=t[0]),n=new kr({props:A}),sn.push(()=>fr(n,"items",_)),n.$on("itemClick",t[3]),{c(){e=r("div"),In(n.$$.fragment),s=p(),u=r("button"),u.textContent="Create menu",d=p(),o=r("button"),o.textContent="Popup",a(u,"class","btn"),a(o,"class","btn")},m(k,y){C(k,e,y),an(n,e,null),i(e,s),i(e,u),i(e,d),i(e,o),c=!0,h||(w=[S(u,"click",t[1]),S(o,"click",t[2])],h=!0)},p(k,[y]){const L={};!l&&y&1&&(l=!0,L.items=k[0],dr(()=>l=!1)),n.$set(L)},i(k){c||(rn(n.$$.fragment,k),c=!0)},o(k){Wn(n.$$.fragment,k),c=!1},d(k){k&&v(e),un(n),h=!1,Ce(w)}}}function ba(t,e,n){let{onMessage:l}=e,s=[],u=null,d=null,o=0;const c=navigator.userAgent.includes("Macintosh");async function h(){d=await Bn.new({text:"app",items:s.map(y=>y.item)})}async function w(){await h(),o=s.length,u=await bt.new({items:[d]}),await(c?u.setAsAppMenu():u.setAsWindowMenu())}async function _(){(!d||o!==s.length)&&await h(),(await bt.new({items:[d]})).popup()}function A(y){l(`Item ${y.detail.text} clicked`)}function k(y){s=y,n(0,s)}return t.$$set=y=>{"onMessage"in y&&n(4,l=y.onMessage)},[s,w,_,A,l,k]}class wa extends xe{constructor(e){super(),Ze(this,e,ba,_a,je,{onMessage:4})}}class Dl extends mr{constructor(e,n){super(e),this.id=n}static async new(e){e!=null&&e.menu&&(e.menu=[e.menu.rid,e.menu.kind]),e!=null&&e.icon&&(e.icon=typeof e.icon=="string"?e.icon:Array.from(e.icon));const n=new Il;return e!=null&&e.action&&(n.onmessage=e.action,delete e.action),m("plugin:tray|new",{options:e??{},handler:n}).then(([l,s])=>new Dl(l,s))}async setIcon(e){let n=null;return e&&(n=typeof e=="string"?e:Array.from(e)),m("plugin:tray|set_icon",{rid:this.rid,icon:n})}async setMenu(e){return e&&(e=[e.rid,e.kind]),m("plugin:tray|set_menu",{rid:this.rid,menu:e})}async setTooltip(e){return m("plugin:tray|set_tooltip",{rid:this.rid,tooltip:e})}async setTitle(e){return m("plugin:tray|set_title",{rid:this.rid,title:e})}async setVisible(e){return m("plugin:tray|set_visible",{rid:this.rid,visible:e})}async setTempDirPath(e){return m("plugin:tray|set_temp_dir_path",{rid:this.rid,path:e})}async setIconAsTemplate(e){return m("plugin:tray|set_icon_as_template",{rid:this.rid,asTemplate:e})}async setMenuOnLeftClick(e){return m("plugin:tray|set_show_menu_on_left_click",{rid:this.rid,onLeft:e})}}function ka(t){let e,n,l,s,u,d,o,c,h,w,_,A,k,y,L,M,B,D,O,P,E,z,R,J,V,Z;function le(q){t[14](q)}let te={};return t[5]!==void 0&&(te.items=t[5]),O=new kr({props:te}),sn.push(()=>fr(O,"items",le)),O.$on("itemClick",t[6]),{c(){e=r("div"),n=r("div"),l=r("input"),s=p(),u=r("input"),d=p(),o=r("label"),c=b(`Menu on left click + `),D=r("div"),O=r("input"),P=p(),E=r("input"),z=p(),R=r("input"),J=p(),V=r("input"),Z=p(),le=r("div"),te=r("button"),te.textContent="Add",q=p(),G=r("div"),T=r("div"),K=b("Applied effects: "),be=b(X),ke=p(),de=r("button"),de.textContent="Clear",a(u,"class","input"),t[36]===void 0&&kt(()=>t[89].call(u)),a(h,"class","input"),t[37]===void 0&&kt(()=>t[90].call(h)),a(k,"class","input"),a(k,"type","number"),a(n,"class","flex"),$t(O,"max-width","120px"),a(O,"class","input"),a(O,"type","number"),a(O,"placeholder","R"),$t(E,"max-width","120px"),a(E,"class","input"),a(E,"type","number"),a(E,"placeholder","G"),$t(R,"max-width","120px"),a(R,"class","input"),a(R,"type","number"),a(R,"placeholder","B"),$t(V,"max-width","120px"),a(V,"class","input"),a(V,"type","number"),a(V,"placeholder","A"),a(D,"class","flex"),a(L,"class","flex"),a(te,"class","btn"),$t(te,"width","80px"),a(le,"class","flex"),a(de,"class","btn"),$t(de,"width","80px"),a(G,"class","flex"),a(e,"class","flex flex-col gap-1")},m(W,x){C(W,e,x),i(e,n),i(n,l),i(l,s),i(l,u);for(let H=0;H=1,w,_,A,k=h&&Fs(t),y=t[1][t[0]]&&Us(t);return{c(){e=r("div"),n=r("div"),l=r("input"),s=p(),u=r("button"),u.textContent="New window",d=p(),o=r("br"),c=p(),k&&k.c(),w=p(),y&&y.c(),a(l,"class","input grow"),a(l,"type","text"),a(l,"placeholder","New Window label.."),a(u,"class","btn"),a(n,"class","flex gap-1"),a(e,"class","flex flex-col children:grow gap-2")},m(L,M){C(L,e,M),i(e,n),i(n,l),I(l,t[28]),i(n,s),i(n,u),i(e,d),i(e,o),i(e,c),k&&k.m(e,null),i(e,w),y&&y.m(e,null),_||(A=[S(l,"input",t[58]),S(u,"click",t[53])],_=!0)},p(L,M){M[0]&268435456&&l.value!==L[28]&&I(l,L[28]),M[0]&2&&(h=Object.keys(L[1]).length>=1),h?k?k.p(L,M):(k=Fs(L),k.c(),k.m(e,w)):k&&(k.d(1),k=null),L[1][L[0]]?y?y.p(L,M):(y=Us(L),y.c(),y.m(e,null)):y&&(y.d(1),y=null)},i:ie,o:ie,d(L){L&&v(e),k&&k.d(),y&&y.d(),_=!1,Ce(A)}}}function ta(t,e,n){const l=br();let s=l.label;const u={[l.label]:l},d=["default","crosshair","hand","arrow","move","text","wait","help","progress","notAllowed","contextMenu","cell","verticalText","alias","copy","noDrop","grab","grabbing","allScroll","zoomIn","zoomOut","eResize","nResize","neResize","nwResize","sResize","seResize","swResize","wResize","ewResize","nsResize","neswResize","nwseResize","colResize","rowResize"],o=["mica","blur","acrylic","tabbed","tabbedDark","tabbedLight"],c=navigator.appVersion.includes("Windows"),h=navigator.appVersion.includes("Macintosh");let w=c?o:Object.keys(Ji).map(N=>Ji[N]).filter(N=>!o.includes(N));const _=Object.keys(Zi).map(N=>Zi[N]),A=Object.keys(Qi).map(N=>Qi[N]);let{onMessage:k}=e;const y=document.querySelector("main");let L,M=!0,B=!0,D=!0,O=!0,P=!1,E=!0,z=!1,R=!1,J=!0,V=!1,Z=null,le=null,te=null,q=null,G=null,T=null,K=null,X=null,be=1,ke=new it(K,X),de=new it(K,X),ae=new sn(Z,le),$=new sn(Z,le),pe,Y,se=!1,ne=!0,W=null,x=null,H="default",ue=!1,Ae="Awesome Tauri Example!",we=[],me,We,Me,Ie,ge,_e,Se,Pe="none",he=0,Le;function oe(){u[s].setTitle(Ae)}function Re(){u[s].hide(),setTimeout(u[s].show,2e3)}function De(){u[s].minimize(),setTimeout(u[s].unminimize,2e3)}function Ee(){if(!L)return;const N=`main-${L}`,ut=new Dn(N);n(1,u[N]=ut,u),ut.once("tauri://error",function(){k("Error creating new webview")})}function ce(){u[s].innerSize().then(N=>{n(32,ae=N),n(12,Z=ae.width),n(13,le=ae.height)}),u[s].outerSize().then(N=>{n(33,$=N)})}function F(){u[s].innerPosition().then(N=>{n(30,ke=N)}),u[s].outerPosition().then(N=>{n(31,de=N),n(18,K=de.x),n(19,X=de.y)})}async function ee(N){N&&(pe&&pe(),Y&&Y(),Y=await N.listen("tauri://move",F),pe=await N.listen("tauri://resize",ce))}async function U(){await u[s].minimize(),await u[s].requestUserAttention(Yi.Critical),await new Promise(N=>setTimeout(N,3e3)),await u[s].requestUserAttention(null)}async function Te(){we.includes(me)||n(35,we=[...we,me]);const N={effects:we,state:We,radius:Me};Number.isInteger(Ie)&&Number.isInteger(ge)&&Number.isInteger(_e)&&Number.isInteger(Se)&&(N.color=[Ie,ge,_e,Se]),y.classList.remove("bg-primary"),y.classList.remove("dark:bg-darkPrimary"),await u[s].clearEffects(),await u[s].setEffects(N)}async function Vn(){n(35,we=[]),await u[s].clearEffects(),y.classList.add("bg-primary"),y.classList.add("dark:bg-darkPrimary")}function Fe(){L=this.value,n(28,L)}function qn(){s=En(this),n(0,s),n(1,u)}function Wt(){Le=this.value,n(43,Le)}const Nn=()=>u[s].center();function He(){P=this.checked,n(6,P)}function jn(){M=this.checked,n(2,M)}function lt(){B=this.checked,n(3,B)}function It(){D=this.checked,n(4,D)}function Gn(){O=this.checked,n(5,O)}function Ue(){E=this.checked,n(7,E)}function Kn(){z=this.checked,n(8,z)}function Rt(){R=this.checked,n(9,R)}function Xn(){J=this.checked,n(10,J)}function Be(){V=this.checked,n(11,V)}function Yn(){K=Q(this.value),n(18,K)}function st(){X=Q(this.value),n(19,X)}function Dt(){Z=Q(this.value),n(12,Z)}function Qn(){le=Q(this.value),n(13,le)}function Ge(){te=Q(this.value),n(14,te)}function Jn(){q=Q(this.value),n(15,q)}function Ft(){G=Q(this.value),n(16,G)}function Zn(){T=Q(this.value),n(17,T)}function Ke(){se=this.checked,n(20,se)}function xn(){ne=this.checked,n(21,ne)}function rt(){ue=this.checked,n(25,ue)}function Ht(){H=En(this),n(24,H),n(44,d)}function $n(){W=Q(this.value),n(22,W)}function Ve(){x=Q(this.value),n(23,x)}function ei(){Ae=this.value,n(34,Ae)}function Ut(){Pe=En(this),n(26,Pe),n(49,A)}function ti(){he=Q(this.value),n(27,he)}function qe(){me=En(this),n(36,me),n(47,w)}function fn(){We=En(this),n(37,We),n(48,_)}function pn(){Me=Q(this.value),n(38,Me)}function mn(){Ie=Q(this.value),n(39,Ie)}function ze(){ge=Q(this.value),n(40,ge)}function at(){_e=Q(this.value),n(41,_e)}function Xe(){Se=Q(this.value),n(42,Se)}return t.$$set=N=>{"onMessage"in N&&n(57,k=N.onMessage)},t.$$.update=()=>{var N,ut,yt,gn,vt,Bt,_n,Ct,bn,St,Vt,wn,Ne,Lt,kn,At,yn,Mt,qt,vn,Pt,Cn,Et,Nt;t.$$.dirty[0]&3&&(u[s],F(),ce()),t.$$.dirty[0]&7&&((N=u[s])==null||N.setResizable(M)),t.$$.dirty[0]&11&&((ut=u[s])==null||ut.setMaximizable(B)),t.$$.dirty[0]&19&&((yt=u[s])==null||yt.setMinimizable(D)),t.$$.dirty[0]&35&&((gn=u[s])==null||gn.setClosable(O)),t.$$.dirty[0]&67&&(P?(vt=u[s])==null||vt.maximize():(Bt=u[s])==null||Bt.unmaximize()),t.$$.dirty[0]&131&&((_n=u[s])==null||_n.setDecorations(E)),t.$$.dirty[0]&259&&((Ct=u[s])==null||Ct.setAlwaysOnTop(z)),t.$$.dirty[0]&515&&((bn=u[s])==null||bn.setAlwaysOnBottom(R)),t.$$.dirty[0]&1027&&((St=u[s])==null||St.setContentProtected(J)),t.$$.dirty[0]&2051&&((Vt=u[s])==null||Vt.setFullscreen(V)),t.$$.dirty[0]&12291&&Z&&le&&((wn=u[s])==null||wn.setSize(new sn(Z,le))),t.$$.dirty[0]&49155&&(te&&q?(Ne=u[s])==null||Ne.setMinSize(new zl(te,q)):(Lt=u[s])==null||Lt.setMinSize(null)),t.$$.dirty[0]&196611&&(G>800&&T>400?(kn=u[s])==null||kn.setMaxSize(new zl(G,T)):(At=u[s])==null||At.setMaxSize(null)),t.$$.dirty[0]&786435&&K!==null&&X!==null&&((yn=u[s])==null||yn.setPosition(new it(K,X))),t.$$.dirty[0]&3&&((Mt=u[s])==null||Mt.scaleFactor().then(ni=>n(29,be=ni))),t.$$.dirty[0]&3&&ee(u[s]),t.$$.dirty[0]&1048579&&((qt=u[s])==null||qt.setCursorGrab(se)),t.$$.dirty[0]&2097155&&((vn=u[s])==null||vn.setCursorVisible(ne)),t.$$.dirty[0]&16777219&&((Pt=u[s])==null||Pt.setCursorIcon(H)),t.$$.dirty[0]&12582915&&W!==null&&x!==null&&((Cn=u[s])==null||Cn.setCursorPosition(new it(W,x))),t.$$.dirty[0]&33554435&&((Et=u[s])==null||Et.setIgnoreCursorEvents(ue)),t.$$.dirty[0]&201326595&&((Nt=u[s])==null||Nt.setProgressBar({status:Pe,progress:he}))},[s,u,M,B,D,O,P,E,z,R,J,V,Z,le,te,q,G,T,K,X,se,ne,W,x,H,ue,Pe,he,L,be,ke,de,ae,$,Ae,we,me,We,Me,Ie,ge,_e,Se,Le,d,c,h,w,_,A,oe,Re,De,Ee,U,Te,Vn,k,Fe,qn,Wt,Nn,He,jn,lt,It,Gn,Ue,Kn,Rt,Xn,Be,Yn,st,Dt,Qn,Ge,Jn,Ft,Zn,Ke,xn,rt,Ht,$n,Ve,ei,Ut,ti,qe,fn,pn,mn,ze,at,Xe]}class na extends xe{constructor(e){super(),Ze(this,e,ta,ea,je,{onMessage:57},null,[-1,-1,-1,-1])}}function ia(t){let e;return{c(){e=r("div"),e.innerHTML='
Not available for Linux
',a(e,"class","flex flex-col gap-2")},m(n,l){C(n,e,l)},p:ie,i:ie,o:ie,d(n){n&&v(e)}}}function la(t,e,n){let{onMessage:l}=e;const s=window.constraints={audio:!0,video:!0};function u(o){const c=document.querySelector("video"),h=o.getVideoTracks();l("Got stream with constraints:",s),l(`Using video device: ${h[0].label}`),window.stream=o,c.srcObject=o}function d(o){if(o.name==="ConstraintNotSatisfiedError"){const c=s.video;l(`The resolution ${c.width.exact}x${c.height.exact} px is not supported by your device.`)}else o.name==="PermissionDeniedError"&&l("Permissions have not been granted to use your camera and microphone, you need to allow the page access to your devices in order for the demo to work.");l(`getUserMedia error: ${o.name}`,o)}return Ki(async()=>{try{const o=await navigator.mediaDevices.getUserMedia(s);u(o)}catch(o){d(o)}}),ar(()=>{var o;(o=window.stream)==null||o.getTracks().forEach(function(c){c.stop()})}),t.$$set=o=>{"onMessage"in o&&n(0,l=o.onMessage)},[l]}class sa extends xe{constructor(e){super(),Ze(this,e,la,ia,je,{onMessage:0})}}function ra(t){let e,n,l,s,u,d;return{c(){e=r("div"),n=r("button"),n.textContent="Show",l=p(),s=r("button"),s.textContent="Hide",a(n,"class","btn"),a(n,"id","show"),a(n,"title","Hides and shows the app after 2 seconds"),a(s,"class","btn"),a(s,"id","hide")},m(o,c){C(o,e,c),i(e,n),i(e,l),i(e,s),u||(d=[S(n,"click",t[0]),S(s,"click",t[1])],u=!0)},p:ie,i:ie,o:ie,d(o){o&&v(e),u=!1,Ce(d)}}}function aa(t,e,n){let{onMessage:l}=e;function s(){u().then(()=>{setTimeout(()=>{Vr().then(()=>l("Shown app")).catch(l)},2e3)}).catch(l)}function u(){return qr().then(()=>l("Hide app")).catch(l)}return t.$$set=d=>{"onMessage"in d&&n(2,l=d.onMessage)},[s,u,l]}class ua extends xe{constructor(e){super(),Ze(this,e,aa,ra,je,{onMessage:2})}}var ji,Gi;function wr(t){var e;if("items"in t)t.items=(e=t.items)==null?void 0:e.map(n=>"rid"in n?n:wr(n));else if("action"in t&&t.action){const n=new Il;return n.onmessage=t.action,delete t.action,{...t,handler:n}}return t}async function cn(t,e){const n=new Il;let l=null;return e&&typeof e=="object"&&("action"in e&&e.action&&(n.onmessage=e.action,delete e.action),"items"in e&&e.items&&(l=e.items.map(s=>"rid"in s?[s.rid,s.kind]:wr(s)))),m("plugin:menu|new",{kind:t,options:e?{...e,items:l}:void 0,handler:n})}class dn extends mr{get id(){return Rn(this,ji,"f")}get kind(){return Rn(this,Gi,"f")}constructor(e,n,l){super(e),ji.set(this,void 0),Gi.set(this,void 0),Xi(this,ji,n,"f"),Xi(this,Gi,l,"f")}}ji=new WeakMap,Gi=new WeakMap;class Fn extends dn{constructor(e,n){super(e,n,"MenuItem")}static async new(e){return cn("MenuItem",e).then(([n,l])=>new Fn(n,l))}async text(){return m("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return m("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return m("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return m("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return m("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}}class hn extends dn{constructor(e,n){super(e,n,"Check")}static async new(e){return cn("Check",e).then(([n,l])=>new hn(n,l))}async text(){return m("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return m("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return m("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return m("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return m("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}async isChecked(){return m("plugin:menu|is_checked",{rid:this.rid})}async setChecked(e){return m("plugin:menu|set_checked",{rid:this.rid,checked:e})}}var js;(function(t){t.Add="Add",t.Advanced="Advanced",t.Bluetooth="Bluetooth",t.Bookmarks="Bookmarks",t.Caution="Caution",t.ColorPanel="ColorPanel",t.ColumnView="ColumnView",t.Computer="Computer",t.EnterFullScreen="EnterFullScreen",t.Everyone="Everyone",t.ExitFullScreen="ExitFullScreen",t.FlowView="FlowView",t.Folder="Folder",t.FolderBurnable="FolderBurnable",t.FolderSmart="FolderSmart",t.FollowLinkFreestanding="FollowLinkFreestanding",t.FontPanel="FontPanel",t.GoLeft="GoLeft",t.GoRight="GoRight",t.Home="Home",t.IChatTheater="IChatTheater",t.IconView="IconView",t.Info="Info",t.InvalidDataFreestanding="InvalidDataFreestanding",t.LeftFacingTriangle="LeftFacingTriangle",t.ListView="ListView",t.LockLocked="LockLocked",t.LockUnlocked="LockUnlocked",t.MenuMixedState="MenuMixedState",t.MenuOnState="MenuOnState",t.MobileMe="MobileMe",t.MultipleDocuments="MultipleDocuments",t.Network="Network",t.Path="Path",t.PreferencesGeneral="PreferencesGeneral",t.QuickLook="QuickLook",t.RefreshFreestanding="RefreshFreestanding",t.Refresh="Refresh",t.Remove="Remove",t.RevealFreestanding="RevealFreestanding",t.RightFacingTriangle="RightFacingTriangle",t.Share="Share",t.Slideshow="Slideshow",t.SmartBadge="SmartBadge",t.StatusAvailable="StatusAvailable",t.StatusNone="StatusNone",t.StatusPartiallyAvailable="StatusPartiallyAvailable",t.StatusUnavailable="StatusUnavailable",t.StopProgressFreestanding="StopProgressFreestanding",t.StopProgress="StopProgress",t.TrashEmpty="TrashEmpty",t.TrashFull="TrashFull",t.User="User",t.UserAccounts="UserAccounts",t.UserGroup="UserGroup",t.UserGuest="UserGuest"})(js||(js={}));class Hn extends dn{constructor(e,n){super(e,n,"Icon")}static async new(e){return cn("Icon",e).then(([n,l])=>new Hn(n,l))}async text(){return m("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return m("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return m("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return m("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return m("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}async setIcon(e){return m("plugin:menu|set_icon",{rid:this.rid,icon:e})}}class Un extends dn{constructor(e,n){super(e,n,"Predefined")}static async new(e){return cn("Predefined",e).then(([n,l])=>new Un(n,l))}async text(){return m("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return m("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}}function Ml([t,e,n]){switch(n){case"Submenu":return new Bn(t,e);case"Predefined":return new Un(t,e);case"Check":return new hn(t,e);case"Icon":return new Hn(t,e);case"MenuItem":default:return new Fn(t,e)}}class Bn extends dn{constructor(e,n){super(e,n,"Submenu")}static async new(e){return cn("Submenu",e).then(([n,l])=>new Bn(n,l))}async text(){return m("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return m("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return m("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return m("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async append(e){return m("plugin:menu|append",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map(n=>"rid"in n?[n.rid,n.kind]:n)})}async prepend(e){return m("plugin:menu|prepend",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map(n=>"rid"in n?[n.rid,n.kind]:n)})}async insert(e,n){return m("plugin:menu|insert",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map(l=>"rid"in l?[l.rid,l.kind]:l),position:n})}async remove(e){return m("plugin:menu|remove",{rid:this.rid,kind:this.kind,item:[e.rid,e.kind]})}async removeAt(e){return m("plugin:menu|remove_at",{rid:this.rid,kind:this.kind,position:e}).then(Ml)}async items(){return m("plugin:menu|items",{rid:this.rid,kind:this.kind}).then(e=>e.map(Ml))}async get(e){return m("plugin:menu|get",{rid:this.rid,kind:this.kind,id:e}).then(n=>n?Ml(n):null)}async popup(e,n){let l=null;return e&&(l={type:e instanceof it?"Physical":"Logical",data:e}),m("plugin:menu|popup",{rid:this.rid,kind:this.kind,window:(n==null?void 0:n.label)??null,at:l})}async setAsWindowsMenuForNSApp(){return m("plugin:menu|set_as_windows_menu_for_nsapp",{rid:this.rid})}async setAsHelpMenuForNSApp(){return m("plugin:menu|set_as_help_menu_for_nsapp",{rid:this.rid})}}function Pl([t,e,n]){switch(n){case"Submenu":return new Bn(t,e);case"Predefined":return new Un(t,e);case"Check":return new hn(t,e);case"Icon":return new Hn(t,e);case"MenuItem":default:return new Fn(t,e)}}class wt extends dn{constructor(e,n){super(e,n,"Menu")}static async new(e){return cn("Menu",e).then(([n,l])=>new wt(n,l))}static async default(){return m("plugin:menu|create_default").then(([e,n])=>new wt(e,n))}async append(e){return m("plugin:menu|append",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map(n=>"rid"in n?[n.rid,n.kind]:n)})}async prepend(e){return m("plugin:menu|prepend",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map(n=>"rid"in n?[n.rid,n.kind]:n)})}async insert(e,n){return m("plugin:menu|insert",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map(l=>"rid"in l?[l.rid,l.kind]:l),position:n})}async remove(e){return m("plugin:menu|remove",{rid:this.rid,kind:this.kind,item:[e.rid,e.kind]})}async removeAt(e){return m("plugin:menu|remove_at",{rid:this.rid,kind:this.kind,position:e}).then(Pl)}async items(){return m("plugin:menu|items",{rid:this.rid,kind:this.kind}).then(e=>e.map(Pl))}async get(e){return m("plugin:menu|get",{rid:this.rid,kind:this.kind,id:e}).then(n=>n?Pl(n):null)}async popup(e,n){let l=null;return e&&(l={type:e instanceof it?"Physical":"Logical",data:e}),m("plugin:menu|popup",{rid:this.rid,kind:this.kind,window:(n==null?void 0:n.label)??null,at:l})}async setAsAppMenu(){return m("plugin:menu|set_as_app_menu",{rid:this.rid}).then(e=>e?new wt(e[0],e[1]):null)}async setAsWindowMenu(e){return m("plugin:menu|set_as_window_menu",{rid:this.rid,window:(e==null?void 0:e.label)??null}).then(n=>n?new wt(n[0],n[1]):null)}}function Gs(t,e,n){const l=t.slice();return l[16]=e[n],l[17]=e,l[18]=n,l}function Ks(t,e,n){const l=t.slice();return l[19]=e[n],l[20]=e,l[21]=n,l}function Xs(t){let e,n,l,s,u,d,o=t[19]+"",c,h,w,_,A;function k(){t[9].call(n,t[20],t[21])}return{c(){e=r("div"),n=r("input"),u=p(),d=r("label"),c=b(o),w=p(),a(n,"id",l=t[19]+"Input"),n.checked=s=t[0]===t[19],a(n,"type","radio"),a(n,"name","kind"),a(d,"for",h=t[19]+"Input"),a(e,"class","flex gap-1")},m(y,L){C(y,e,L),i(e,n),I(n,t[19]),i(e,u),i(e,d),i(d,c),i(e,w),_||(A=[S(n,"change",t[6]),S(n,"change",k)],_=!0)},p(y,L){t=y,L&16&&l!==(l=t[19]+"Input")&&a(n,"id",l),L&17&&s!==(s=t[0]===t[19])&&(n.checked=s),L&16&&I(n,t[19]),L&16&&o!==(o=t[19]+"")&&re(c,o),L&16&&h!==(h=t[19]+"Input")&&a(d,"for",h)},d(y){y&&v(e),_=!1,Ce(A)}}}function Ys(t){let e,n,l;return{c(){e=r("input"),a(e,"class","input"),a(e,"type","text"),a(e,"placeholder","Text")},m(s,u){C(s,e,u),I(e,t[1]),n||(l=S(e,"input",t[10]),n=!0)},p(s,u){u&2&&e.value!==s[1]&&I(e,s[1])},d(s){s&&v(e),n=!1,l()}}}function oa(t){let e,n=fe(t[5]),l=[];for(let s=0;sl("itemClick",{id:z,text:E})},P=await Fn.new(O);break;case"Icon":O={text:u,icon:d,action:z=>l("itemClick",{id:z,text:E})},P=await Hn.new(O);break;case"Check":O={text:u,checked:c,action:z=>l("itemClick",{id:z,text:E})},P=await hn.new(O);break;case"Predefined":O={item:o},P=await Un.new(O);break}l("new",{item:P,options:O}),n(1,u=""),o=""}function y(O,P){O[P]=this.value,n(4,h)}function L(){u=this.value,n(1,u)}function M(){d=this.value,n(2,d)}function B(){c=this.checked,n(3,c)}function D(O,P){O[P]=this.value,n(5,w)}return[s,u,d,c,h,w,_,A,k,y,L,M,B,D]}class pa extends xe{constructor(e){super(),Ze(this,e,fa,ha,je,{})}}function Js(t,e,n){const l=t.slice();return l[5]=e[n],l}function Zs(t){let e,n,l,s,u,d=xs(t[5])+"",o,c;return{c(){e=r("div"),n=r("div"),s=p(),u=r("p"),o=b(d),c=p(),a(n,"class",l=t[3](t[5])),a(e,"class","flex flex-row gap-1")},m(h,w){C(h,e,w),i(e,n),i(e,s),i(e,u),i(u,o),i(e,c)},p(h,w){w&1&&l!==(l=h[3](h[5]))&&a(n,"class",l),w&1&&d!==(d=xs(h[5])+"")&&re(o,d)},d(h){h&&v(e)}}}function ma(t){let e,n,l,s,u;n=new pa({}),n.$on("new",t[1]),n.$on("itemClick",t[2]);let d=fe(t[0]),o=[];for(let c=0;c{"items"in c&&n(0,l=c.items)},[l,u,d,o]}class kr extends xe{constructor(e){super(),Ze(this,e,ga,ma,je,{items:0})}}function _a(t){let e,n,l,s,u,d,o,c,h,w;function _(k){t[5](k)}let A={};return t[0]!==void 0&&(A.items=t[0]),n=new kr({props:A}),rn.push(()=>fr(n,"items",_)),n.$on("itemClick",t[3]),{c(){e=r("div"),In(n.$$.fragment),s=p(),u=r("button"),u.textContent="Create menu",d=p(),o=r("button"),o.textContent="Popup",a(u,"class","btn"),a(o,"class","btn")},m(k,y){C(k,e,y),un(n,e,null),i(e,s),i(e,u),i(e,d),i(e,o),c=!0,h||(w=[S(u,"click",t[1]),S(o,"click",t[2])],h=!0)},p(k,[y]){const L={};!l&&y&1&&(l=!0,L.items=k[0],dr(()=>l=!1)),n.$set(L)},i(k){c||(an(n.$$.fragment,k),c=!0)},o(k){Wn(n.$$.fragment,k),c=!1},d(k){k&&v(e),on(n),h=!1,Ce(w)}}}function ba(t,e,n){let{onMessage:l}=e,s=[],u=null,d=null,o=0;const c=navigator.userAgent.includes("Macintosh");async function h(){d=await Bn.new({text:"app",items:s.map(y=>y.item)})}async function w(){await h(),o=s.length,u=await wt.new({items:[d]}),await(c?u.setAsAppMenu():u.setAsWindowMenu())}async function _(){(!d||o!==s.length)&&await h(),(await wt.new({items:[d]})).popup()}function A(y){l(`Item ${y.detail.text} clicked`)}function k(y){s=y,n(0,s)}return t.$$set=y=>{"onMessage"in y&&n(4,l=y.onMessage)},[s,w,_,A,l,k]}class wa extends xe{constructor(e){super(),Ze(this,e,ba,_a,je,{onMessage:4})}}class Dl extends mr{constructor(e,n){super(e),this.id=n}static async new(e){e!=null&&e.menu&&(e.menu=[e.menu.rid,e.menu.kind]),e!=null&&e.icon&&(e.icon=typeof e.icon=="string"?e.icon:Array.from(e.icon));const n=new Il;return e!=null&&e.action&&(n.onmessage=e.action,delete e.action),m("plugin:tray|new",{options:e??{},handler:n}).then(([l,s])=>new Dl(l,s))}async setIcon(e){let n=null;return e&&(n=typeof e=="string"?e:Array.from(e)),m("plugin:tray|set_icon",{rid:this.rid,icon:n})}async setMenu(e){return e&&(e=[e.rid,e.kind]),m("plugin:tray|set_menu",{rid:this.rid,menu:e})}async setTooltip(e){return m("plugin:tray|set_tooltip",{rid:this.rid,tooltip:e})}async setTitle(e){return m("plugin:tray|set_title",{rid:this.rid,title:e})}async setVisible(e){return m("plugin:tray|set_visible",{rid:this.rid,visible:e})}async setTempDirPath(e){return m("plugin:tray|set_temp_dir_path",{rid:this.rid,path:e})}async setIconAsTemplate(e){return m("plugin:tray|set_icon_as_template",{rid:this.rid,asTemplate:e})}async setMenuOnLeftClick(e){return m("plugin:tray|set_show_menu_on_left_click",{rid:this.rid,onLeft:e})}}function ka(t){let e,n,l,s,u,d,o,c,h,w,_,A,k,y,L,M,B,D,O,P,E,z,R,J,V,Z;function le(q){t[14](q)}let te={};return t[5]!==void 0&&(te.items=t[5]),O=new kr({props:te}),rn.push(()=>fr(O,"items",le)),O.$on("itemClick",t[6]),{c(){e=r("div"),n=r("div"),l=r("input"),s=p(),u=r("input"),d=p(),o=r("label"),c=b(`Menu on left click `),h=r("input"),w=p(),_=r("div"),A=r("input"),k=p(),y=r("label"),L=b(`Icon as template - `),M=r("input"),B=p(),D=r("div"),In(O.$$.fragment),E=p(),z=r("div"),R=r("button"),R.textContent="Create tray",a(l,"class","input grow"),a(l,"type","text"),a(l,"placeholder","Title"),a(u,"class","input grow"),a(u,"type","text"),a(u,"placeholder","Tooltip"),a(h,"type","checkbox"),a(n,"class","flex gap-1"),a(A,"class","input grow"),a(A,"type","text"),a(A,"placeholder","Icon path"),a(M,"type","checkbox"),a(_,"class","flex gap-1"),a(D,"class","flex children:grow"),a(R,"class","btn"),a(R,"title","Creates the tray icon"),a(z,"class","flex"),a(e,"class","flex flex-col children:grow gap-2")},m(q,G){C(q,e,G),i(e,n),i(n,l),I(l,t[2]),i(n,s),i(n,u),I(u,t[1]),i(n,d),i(n,o),i(o,c),i(o,h),h.checked=t[4],i(e,w),i(e,_),i(_,A),I(A,t[0]),i(_,k),i(_,y),i(y,L),i(y,M),M.checked=t[3],i(e,B),i(e,D),an(O,D,null),i(e,E),i(e,z),i(z,R),J=!0,V||(Z=[S(l,"input",t[9]),S(u,"input",t[10]),S(h,"change",t[11]),S(A,"input",t[12]),S(M,"change",t[13]),S(R,"click",t[7])],V=!0)},p(q,[G]){G&4&&l.value!==q[2]&&I(l,q[2]),G&2&&u.value!==q[1]&&I(u,q[1]),G&16&&(h.checked=q[4]),G&1&&A.value!==q[0]&&I(A,q[0]),G&8&&(M.checked=q[3]);const T={};!P&&G&32&&(P=!0,T.items=q[5],dr(()=>P=!1)),O.$set(T)},i(q){J||(rn(O.$$.fragment,q),J=!0)},o(q){Wn(O.$$.fragment,q),J=!1},d(q){q&&v(e),un(O),V=!1,Ce(Z)}}}function ya(t,e,n){let{onMessage:l}=e,s=null,u=null,d=null,o=!1,c=!0,h=[];function w(D){l(`Item ${D.detail.text} clicked`)}async function _(){Dl.new({icon:s,tooltip:u,title:d,iconAsTemplate:o,menuOnLeftClick:c,menu:await bt.new({items:h.map(D=>D.item)}),action:D=>l(D)}).catch(l)}function A(){d=this.value,n(2,d)}function k(){u=this.value,n(1,u)}function y(){c=this.checked,n(4,c)}function L(){s=this.value,n(0,s)}function M(){o=this.checked,n(3,o)}function B(D){h=D,n(5,h)}return t.$$set=D=>{"onMessage"in D&&n(8,l=D.onMessage)},[s,u,d,o,c,h,w,_,l,A,k,y,L,M,B]}class va extends xe{constructor(e){super(),Ze(this,e,ya,ka,je,{onMessage:8})}}function $s(t,e,n){const l=t.slice();return l[28]=e[n],l}function er(t,e,n){const l=t.slice();return l[31]=e[n],l}function Ca(t){let e;return{c(){e=r("span"),a(e,"class","i-codicon-menu animate-duration-300ms animate-fade-in")},m(n,l){C(n,e,l)},d(n){n&&v(e)}}}function Sa(t){let e;return{c(){e=r("span"),a(e,"class","i-codicon-close animate-duration-300ms animate-fade-in")},m(n,l){C(n,e,l)},d(n){n&&v(e)}}}function La(t){let e,n;return{c(){e=b(`Switch to Dark mode + `),M=r("input"),B=p(),D=r("div"),In(O.$$.fragment),E=p(),z=r("div"),R=r("button"),R.textContent="Create tray",a(l,"class","input grow"),a(l,"type","text"),a(l,"placeholder","Title"),a(u,"class","input grow"),a(u,"type","text"),a(u,"placeholder","Tooltip"),a(h,"type","checkbox"),a(n,"class","flex gap-1"),a(A,"class","input grow"),a(A,"type","text"),a(A,"placeholder","Icon path"),a(M,"type","checkbox"),a(_,"class","flex gap-1"),a(D,"class","flex children:grow"),a(R,"class","btn"),a(R,"title","Creates the tray icon"),a(z,"class","flex"),a(e,"class","flex flex-col children:grow gap-2")},m(q,G){C(q,e,G),i(e,n),i(n,l),I(l,t[2]),i(n,s),i(n,u),I(u,t[1]),i(n,d),i(n,o),i(o,c),i(o,h),h.checked=t[4],i(e,w),i(e,_),i(_,A),I(A,t[0]),i(_,k),i(_,y),i(y,L),i(y,M),M.checked=t[3],i(e,B),i(e,D),un(O,D,null),i(e,E),i(e,z),i(z,R),J=!0,V||(Z=[S(l,"input",t[9]),S(u,"input",t[10]),S(h,"change",t[11]),S(A,"input",t[12]),S(M,"change",t[13]),S(R,"click",t[7])],V=!0)},p(q,[G]){G&4&&l.value!==q[2]&&I(l,q[2]),G&2&&u.value!==q[1]&&I(u,q[1]),G&16&&(h.checked=q[4]),G&1&&A.value!==q[0]&&I(A,q[0]),G&8&&(M.checked=q[3]);const T={};!P&&G&32&&(P=!0,T.items=q[5],dr(()=>P=!1)),O.$set(T)},i(q){J||(an(O.$$.fragment,q),J=!0)},o(q){Wn(O.$$.fragment,q),J=!1},d(q){q&&v(e),on(O),V=!1,Ce(Z)}}}function ya(t,e,n){let{onMessage:l}=e,s=null,u=null,d=null,o=!1,c=!0,h=[];function w(D){l(`Item ${D.detail.text} clicked`)}async function _(){Dl.new({icon:s,tooltip:u,title:d,iconAsTemplate:o,menuOnLeftClick:c,menu:await wt.new({items:h.map(D=>D.item)}),action:D=>l(D)}).catch(l)}function A(){d=this.value,n(2,d)}function k(){u=this.value,n(1,u)}function y(){c=this.checked,n(4,c)}function L(){s=this.value,n(0,s)}function M(){o=this.checked,n(3,o)}function B(D){h=D,n(5,h)}return t.$$set=D=>{"onMessage"in D&&n(8,l=D.onMessage)},[s,u,d,o,c,h,w,_,l,A,k,y,L,M,B]}class va extends xe{constructor(e){super(),Ze(this,e,ya,ka,je,{onMessage:8})}}function $s(t,e,n){const l=t.slice();return l[28]=e[n],l}function er(t,e,n){const l=t.slice();return l[31]=e[n],l}function Ca(t){let e;return{c(){e=r("span"),a(e,"class","i-codicon-menu animate-duration-300ms animate-fade-in")},m(n,l){C(n,e,l)},d(n){n&&v(e)}}}function Sa(t){let e;return{c(){e=r("span"),a(e,"class","i-codicon-close animate-duration-300ms animate-fade-in")},m(n,l){C(n,e,l)},d(n){n&&v(e)}}}function La(t){let e,n;return{c(){e=b(`Switch to Dark mode `),n=r("div"),a(n,"class","i-ph-moon")},m(l,s){C(l,e,s),C(l,n,s)},d(l){l&&(v(e),v(n))}}}function Aa(t){let e,n;return{c(){e=b(`Switch to Light mode `),n=r("div"),a(n,"class","i-ph-sun")},m(l,s){C(l,e,s),C(l,n,s)},d(l){l&&(v(e),v(n))}}}function Ma(t){let e,n,l,s,u,d,o;function c(){return t[15](t[31])}return{c(){e=r("a"),n=r("div"),l=p(),s=r("p"),s.textContent=`${t[31].label}`,a(n,"class",t[31].icon+" mr-2"),a(e,"href","##"),a(e,"class",u="nv "+(t[1]===t[31]?"nv_selected":""))},m(h,w){C(h,e,w),i(e,n),i(e,l),i(e,s),d||(o=S(e,"click",c),d=!0)},p(h,w){t=h,w[0]&2&&u!==(u="nv "+(t[1]===t[31]?"nv_selected":""))&&a(e,"class",u)},d(h){h&&v(e),d=!1,o()}}}function tr(t){let e,n=t[31]&&Ma(t);return{c(){n&&n.c(),e=Ol()},m(l,s){n&&n.m(l,s),C(l,e,s)},p(l,s){l[31]&&n.p(l,s)},d(l){l&&v(e),n&&n.d(l)}}}function nr(t){let e,n=t[28].html+"",l;return{c(){e=new Tr(!1),l=Ol(),e.a=l},m(s,u){e.m(n,s,u),C(s,l,u)},p(s,u){u[0]&32&&n!==(n=s[28].html+"")&&e.p(n)},d(s){s&&(v(l),e.d())}}}function Pa(t){let e,n,l,s,u,d,o,c,h,w,_,A,k,y,L,M,B,D,O,P,E,z,R,J,V,Z,le,te,q,G,T,K,X=t[1].label+"",be,ke,de,ae,$,pe,Y,se,ne,W,x,H,ue,Ae,we,me,We,Me;function Ie(F,ee){return F[0]?Sa:Ca}let ge=Ie(t),_e=ge(t);function Se(F,ee){return F[2]?Aa:La}let Pe=Se(t),he=Pe(t),Le=fe(t[6]),oe=[];for(let F=0;F`,B=p(),D=r("a"),D.innerHTML=`GitHub `,O=p(),P=r("a"),P.innerHTML=`Source - `,E=p(),z=r("br"),R=p(),J=r("div"),V=p(),Z=r("br"),le=p(),te=r("div");for(let F=0;F',Ae=p(),we=r("div");for(let F=0;F{un(U,1)}),Ir()}Re?($=Es(Re,De(F)),In($.$$.fragment),rn($.$$.fragment,1),an($,ae,null)):$=null}if(ee[0]&32){Ee=fe(F[5]);let U;for(U=0;U{T.ctrlKey&&T.key==="b"&&m("toggle_menu")});const s=navigator.userAgent.toLowerCase(),u=s.includes("android")||s.includes("iphone"),d=[{label:"Welcome",component:Gr,icon:"i-ph-hand-waving"},{label:"Communication",component:Qr,icon:"i-codicon-radio-tower"},!u&&{label:"App",component:ua,icon:"i-codicon-hubot"},{label:"Window",component:na,icon:"i-codicon-window"},{label:"Menu",component:wa,icon:"i-ph-list"},{label:"Tray",component:va,icon:"i-ph-tray"},{label:"WebRTC",component:sa,icon:"i-ph-broadcast"}];let o=d[0];function c(T){n(1,o=T)}let h;Ki(()=>{n(2,h=localStorage&&localStorage.getItem("theme")=="dark"),lr(h)});function w(){n(2,h=!h),lr(h)}let _=Fr([]);Ar(t,_,T=>n(5,l=T));let A;async function k(T){_.update(K=>[...K,{html:`
[${new Date().toLocaleTimeString()}]: `+(typeof T=="string"?T:JSON.stringify(T,null,1))+"
"}]),await Ts(),A&&n(3,A.scrollTop=A.scrollHeight,A)}async function y(T){_.update(K=>[...K,{html:`
[${new Date().toLocaleTimeString()}]: `+T+"
"}]),await Ts(),A&&n(3,A.scrollTop=A.scrollHeight,A)}function L(){_.update(()=>[])}let M,B,D;function O(T){D=T.clientY;const K=window.getComputedStyle(M);B=parseInt(K.height,10);const X=ke=>{const de=ke.clientY-D,ae=B-de;n(4,M.style.height=`${ae{document.removeEventListener("mouseup",be),document.removeEventListener("mousemove",X)};document.addEventListener("mouseup",be),document.addEventListener("mousemove",X)}let P=!1,E,z,R=!1,J=0,V=0;const Z=(T,K,X)=>Math.min(Math.max(K,T),X);Ki(()=>{n(14,E=document.querySelector("#sidebar")),z=document.querySelector("#sidebarToggle"),document.addEventListener("click",T=>{z.contains(T.target)?n(0,P=!P):P&&!E.contains(T.target)&&n(0,P=!1)}),document.addEventListener("touchstart",T=>{if(z.contains(T.target))return;const K=T.touches[0].clientX;(0{if(R){const K=T.touches[0].clientX;V=K;const X=(K-J)/10;E.style.setProperty("--translate-x",`-${Z(0,P?0-X:18.75-X,18.75)}rem`)}}),document.addEventListener("touchend",()=>{if(R){const T=(V-J)/10;n(0,P=P?T>-(18.75/2):T>18.75/2)}R=!1})});const le=T=>{c(T),n(0,P=!1)},te=T=>T.key==="Enter"?L():{};function q(T){sn[T?"unshift":"push"](()=>{A=T,n(3,A)})}function G(T){sn[T?"unshift":"push"](()=>{M=T,n(4,M)})}return t.$$.update=()=>{if(t.$$.dirty[0]&1){const T=document.querySelector("#sidebar");T&&Ea(T,P)}},[P,o,h,A,M,l,d,c,w,_,k,y,L,O,E,le,te,q,G]}class za extends xe{constructor(e){super(),Ze(this,e,Ta,Pa,je,{},null,[-1,-1])}}new za({target:document.querySelector("#app")}); + `,E=p(),z=r("br"),R=p(),J=r("div"),V=p(),Z=r("br"),le=p(),te=r("div");for(let F=0;F',Ae=p(),we=r("div");for(let F=0;F{on(U,1)}),Ir()}Re?($=Es(Re,De(F)),In($.$$.fragment),an($.$$.fragment,1),un($,ae,null)):$=null}if(ee[0]&32){Ee=fe(F[5]);let U;for(U=0;U{T.ctrlKey&&T.key==="b"&&m("toggle_menu")});const s=navigator.userAgent.toLowerCase(),u=s.includes("android")||s.includes("iphone"),d=[{label:"Welcome",component:Gr,icon:"i-ph-hand-waving"},{label:"Communication",component:Qr,icon:"i-codicon-radio-tower"},!u&&{label:"App",component:ua,icon:"i-codicon-hubot"},{label:"Window",component:na,icon:"i-codicon-window"},{label:"Menu",component:wa,icon:"i-ph-list"},{label:"Tray",component:va,icon:"i-ph-tray"},{label:"WebRTC",component:sa,icon:"i-ph-broadcast"}];let o=d[0];function c(T){n(1,o=T)}let h;Ki(()=>{n(2,h=localStorage&&localStorage.getItem("theme")=="dark"),lr(h)});function w(){n(2,h=!h),lr(h)}let _=Fr([]);Ar(t,_,T=>n(5,l=T));let A;async function k(T){_.update(K=>[...K,{html:`
[${new Date().toLocaleTimeString()}]: `+(typeof T=="string"?T:JSON.stringify(T,null,1))+"
"}]),await Ts(),A&&n(3,A.scrollTop=A.scrollHeight,A)}async function y(T){_.update(K=>[...K,{html:`
[${new Date().toLocaleTimeString()}]: `+T+"
"}]),await Ts(),A&&n(3,A.scrollTop=A.scrollHeight,A)}function L(){_.update(()=>[])}let M,B,D;function O(T){D=T.clientY;const K=window.getComputedStyle(M);B=parseInt(K.height,10);const X=ke=>{const de=ke.clientY-D,ae=B-de;n(4,M.style.height=`${ae{document.removeEventListener("mouseup",be),document.removeEventListener("mousemove",X)};document.addEventListener("mouseup",be),document.addEventListener("mousemove",X)}let P=!1,E,z,R=!1,J=0,V=0;const Z=(T,K,X)=>Math.min(Math.max(K,T),X);Ki(()=>{n(14,E=document.querySelector("#sidebar")),z=document.querySelector("#sidebarToggle"),document.addEventListener("click",T=>{z.contains(T.target)?n(0,P=!P):P&&!E.contains(T.target)&&n(0,P=!1)}),document.addEventListener("touchstart",T=>{if(z.contains(T.target))return;const K=T.touches[0].clientX;(0{if(R){const K=T.touches[0].clientX;V=K;const X=(K-J)/10;E.style.setProperty("--translate-x",`-${Z(0,P?0-X:18.75-X,18.75)}rem`)}}),document.addEventListener("touchend",()=>{if(R){const T=(V-J)/10;n(0,P=P?T>-(18.75/2):T>18.75/2)}R=!1})});const le=T=>{c(T),n(0,P=!1)},te=T=>T.key==="Enter"?L():{};function q(T){rn[T?"unshift":"push"](()=>{A=T,n(3,A)})}function G(T){rn[T?"unshift":"push"](()=>{M=T,n(4,M)})}return t.$$.update=()=>{if(t.$$.dirty[0]&1){const T=document.querySelector("#sidebar");T&&Ea(T,P)}},[P,o,h,A,M,l,d,c,w,_,k,y,L,O,E,le,te,q,G]}class za extends xe{constructor(e){super(),Ze(this,e,Ta,Pa,je,{},null,[-1,-1])}}new za({target:document.querySelector("#app")}); diff --git a/examples/api/src-tauri/capabilities/run-app.toml b/examples/api/src-tauri/capabilities/run-app.toml index a4fd8c4fd368..b61789625349 100644 --- a/examples/api/src-tauri/capabilities/run-app.toml +++ b/examples/api/src-tauri/capabilities/run-app.toml @@ -1,7 +1,7 @@ "$schema" = ".schema.json" identifier = "run-app" description = "app capability" -windows = ["main"] +windows = ["main", "main-*"] permissions = [ "path:default", "event:default", diff --git a/examples/api/src/views/Window.svelte b/examples/api/src/views/Window.svelte index 7e31d7f4f8d3..8e5474320353 100644 --- a/examples/api/src/views/Window.svelte +++ b/examples/api/src/views/Window.svelte @@ -79,7 +79,9 @@ (state) => EffectState[state] ) - const progressBarStatusOptions = Object.keys(ProgressBarStatus).map(s => ProgressBarStatus[s]) + const progressBarStatusOptions = Object.keys(ProgressBarStatus).map( + (s) => ProgressBarStatus[s] + ) export let onMessage const mainEl = document.querySelector('main') @@ -152,8 +154,9 @@ function createWindow() { if (!newWindowLabel) return - const webview = new Window(newWindowLabel) - windowMap[newWindowLabel] = webview + const label = `main-${newWindowLabel}` + const webview = new Window(label) + windowMap[label] = webview webview.once('tauri://error', function () { onMessage('Error creating new webview') }) @@ -282,7 +285,10 @@ new PhysicalPosition(cursorX, cursorY) ) $: windowMap[selectedWindow]?.setIgnoreCursorEvents(cursorIgnoreEvents) - $: windowMap[selectedWindow]?.setProgressBar({ status: selectedProgressBarStatus, progress }) + $: windowMap[selectedWindow]?.setProgressBar({ + status: selectedProgressBarStatus, + progress + })
@@ -310,7 +316,11 @@
- +
@@ -557,7 +567,13 @@
From a1cdcd003ee32344f4a3494b3e43c12442c4fe49 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Thu, 18 Jan 2024 09:11:57 -0300 Subject: [PATCH 58/69] add platforms for capability [skip ci] --- core/tauri-build/src/acl.rs | 10 ++++++ core/tauri-codegen/src/context.rs | 2 +- core/tauri-utils/src/acl/capability.rs | 46 +++++++++++++++++++++++++- core/tauri-utils/src/acl/resolved.rs | 11 ++++++ 4 files changed, 67 insertions(+), 2 deletions(-) diff --git a/core/tauri-build/src/acl.rs b/core/tauri-build/src/acl.rs index 47b278fbdbd4..14028d781f4b 100644 --- a/core/tauri-build/src/acl.rs +++ b/core/tauri-build/src/acl.rs @@ -104,7 +104,17 @@ pub fn validate_capabilities( plugin_manifests: &BTreeMap, capabilities: &BTreeMap, ) -> Result<()> { + let target = tauri_utils::platform::Target::from_triple(&std::env::var("TARGET").unwrap()); + for capability in capabilities.values() { + if !capability + .platforms + .iter() + .any(|platform| platform.matches(&target)) + { + continue; + } + for permission in &capability.permissions { if let Some((plugin_name, permission_name)) = permission.get().split_once(':') { let permission_exists = plugin_manifests diff --git a/core/tauri-codegen/src/context.rs b/core/tauri-codegen/src/context.rs index e4c7c7483458..559f6041f6b4 100644 --- a/core/tauri-codegen/src/context.rs +++ b/core/tauri-codegen/src/context.rs @@ -398,7 +398,7 @@ pub fn context_codegen(data: ContextData) -> Result, /// List of permissions attached to this capability. Must include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`. pub permissions: Vec, + /// Target platforms this capability applies. By default all platforms applies. + #[serde(default = "default_platforms")] + pub platforms: Vec, +} + +fn default_platforms() -> Vec { + vec![CapabilityPlatform::Desktop, CapabilityPlatform::Mobile] +} + +/// Target platform of a capability. +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] +#[serde(rename_all = "camelCase")] +pub enum CapabilityPlatform { + /// Windows. + Windows, + /// Linux. + Linux, + /// macOS. + #[serde(rename = "macOS")] + MacOS, + /// Android. + Android, + /// iOS + #[serde(rename = "iOS")] + Ios, + /// Desktop. + Desktop, + /// Mobile. + Mobile, +} + +impl CapabilityPlatform { + /// Checks if the platform matches the given [`Target`]. + pub fn matches(&self, target: &Target) -> bool { + match (self, target) { + (Self::Windows | Self::Desktop, Target::Windows) => true, + (Self::Linux | Self::Desktop, Target::Linux) => true, + (Self::MacOS | Self::Desktop, Target::Darwin) => true, + (Self::Android | Self::Mobile, Target::Android) => true, + (Self::Ios | Self::Mobile, Target::Ios) => true, + _ => false, + } + } } /// Context of the capability. diff --git a/core/tauri-utils/src/acl/resolved.rs b/core/tauri-utils/src/acl/resolved.rs index 5dbe8925f2ed..b9c0087e5896 100644 --- a/core/tauri-utils/src/acl/resolved.rs +++ b/core/tauri-utils/src/acl/resolved.rs @@ -9,6 +9,8 @@ use std::{ hash::{Hash, Hasher}, }; +use crate::platform::Target; + use super::{ capability::{Capability, CapabilityContext}, plugin::Manifest, @@ -64,6 +66,7 @@ impl Resolved { pub fn resolve( acl: BTreeMap, capabilities: BTreeMap, + target: Target, ) -> Result { let mut allowed_commands = BTreeMap::new(); let mut denied_commands = BTreeMap::new(); @@ -74,6 +77,14 @@ impl Resolved { // resolve commands for capability in capabilities.values() { + if !capability + .platforms + .iter() + .any(|platform| platform.matches(&target)) + { + continue; + } + for permission_id in &capability.permissions { let permission_name = permission_id.get_base(); From a146a897c17202e4a8e258d1b325cf46082ac30e Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Thu, 18 Jan 2024 10:14:57 -0300 Subject: [PATCH 59/69] per platform schema [skip ci] --- core/tauri-build/src/acl.rs | 33 +++++-- core/tauri-build/src/lib.rs | 9 +- core/tauri-utils/src/acl/build.rs | 14 ++- core/tauri-utils/src/platform.rs | 21 ++++- core/tauri/src/command/authority.rs | 2 +- .../api/src-tauri/capabilities/.gitignore | 2 +- .../api/src-tauri/capabilities/run-app.json | 89 +++++++++++++++++++ .../api/src-tauri/capabilities/run-app.toml | 88 ------------------ 8 files changed, 148 insertions(+), 110 deletions(-) create mode 100644 examples/api/src-tauri/capabilities/run-app.json delete mode 100644 examples/api/src-tauri/capabilities/run-app.toml diff --git a/core/tauri-build/src/acl.rs b/core/tauri-build/src/acl.rs index 14028d781f4b..8bf627a70a68 100644 --- a/core/tauri-build/src/acl.rs +++ b/core/tauri-build/src/acl.rs @@ -4,7 +4,7 @@ use std::{ collections::BTreeMap, - fs::{create_dir_all, File}, + fs::{copy, create_dir_all, File}, io::{BufWriter, Write}, path::PathBuf, }; @@ -14,9 +14,13 @@ use schemars::{ schema::{InstanceType, Metadata, RootSchema, Schema, SchemaObject, SubschemaValidation}, schema_for, }; -use tauri_utils::acl::{build::CapabilityFile, capability::Capability, plugin::Manifest}; +use tauri_utils::{ + acl::{build::CapabilityFile, capability::Capability, plugin::Manifest}, + platform::Target, +}; -const CAPABILITIES_SCHEMA_FILE_NAME: &str = ".schema.json"; +const CAPABILITIES_SCHEMA_FILE_NAME: &str = "schema.json"; +const CAPABILITIES_SCHEMA_FOLDER_NAME: &str = "schemas"; fn capabilities_schema(plugin_manifests: &BTreeMap) -> RootSchema { let mut schema = schema_for!(CapabilityFile); @@ -77,14 +81,31 @@ fn capabilities_schema(plugin_manifests: &BTreeMap) -> RootSch schema } -pub fn generate_schema(plugin_manifests: &BTreeMap) -> Result<()> { +pub fn generate_schema( + plugin_manifests: &BTreeMap, + target: Target, +) -> Result<()> { let schema = capabilities_schema(plugin_manifests); let schema_str = serde_json::to_string_pretty(&schema).unwrap(); - let out_dir = PathBuf::from("capabilities"); + let out_dir = PathBuf::from("capabilities").join(CAPABILITIES_SCHEMA_FOLDER_NAME); create_dir_all(&out_dir).context("unable to create schema output directory")?; - let mut schema_file = BufWriter::new(File::create(out_dir.join(CAPABILITIES_SCHEMA_FILE_NAME))?); + let schema_path = out_dir.join(format!("{target}-{CAPABILITIES_SCHEMA_FILE_NAME}")); + let mut schema_file = BufWriter::new(File::create(&schema_path)?); write!(schema_file, "{schema_str}")?; + + copy( + schema_path, + out_dir.join(format!( + "{}-{CAPABILITIES_SCHEMA_FILE_NAME}", + if target.is_desktop() { + "desktop" + } else { + "mobile" + } + )), + )?; + Ok(()) } diff --git a/core/tauri-build/src/lib.rs b/core/tauri-build/src/lib.rs index 6836ea32819b..02e6ec1e6a26 100644 --- a/core/tauri-build/src/lib.rs +++ b/core/tauri-build/src/lib.rs @@ -412,8 +412,11 @@ pub fn try_build(attributes: Attributes) -> Result<()> { cfg_alias("desktop", !mobile); cfg_alias("mobile", mobile); + let target_triple = std::env::var("TARGET").unwrap(); + let target = tauri_utils::platform::Target::from_triple(&target_triple); + let mut config = serde_json::from_value(tauri_utils::config::parse::read_from( - tauri_utils::platform::Target::from_triple(&std::env::var("TARGET").unwrap()), + target, std::env::current_dir().unwrap(), )?)?; if let Ok(env) = std::env::var("TAURI_CONFIG") { @@ -467,7 +470,7 @@ pub fn try_build(attributes: Attributes) -> Result<()> { } else { parse_capabilities("./capabilities/**/*")? }; - acl::generate_schema(&plugin_manifests)?; + acl::generate_schema(&plugin_manifests, target)?; acl::validate_capabilities(&plugin_manifests, &capabilities)?; @@ -476,8 +479,6 @@ pub fn try_build(attributes: Attributes) -> Result<()> { serde_json::to_string(&capabilities)?, )?; - let target_triple = std::env::var("TARGET").unwrap(); - println!("cargo:rustc-env=TAURI_ENV_TARGET_TRIPLE={target_triple}"); // TODO: far from ideal, but there's no other way to get the target dir, see diff --git a/core/tauri-utils/src/acl/build.rs b/core/tauri-utils/src/acl/build.rs index aff903ed648a..5e4e854cd26a 100644 --- a/core/tauri-utils/src/acl/build.rs +++ b/core/tauri-utils/src/acl/build.rs @@ -33,8 +33,8 @@ pub const PERMISSION_SCHEMA_FILE_NAME: &str = ".schema.json"; /// Allowed capability file extensions const CAPABILITY_FILE_EXTENSIONS: &[&str] = &["json", "toml"]; -/// Known filename of a capability schema -const CAPABILITIES_SCHEMA_FILE_NAME: &str = ".schema.json"; +/// Known folder name of the capability schemas +const CAPABILITIES_SCHEMA_FOLDER_NAME: &str = "schemas"; const CORE_PLUGIN_PERMISSIONS_TOKEN: &str = "__CORE_PLUGIN__"; @@ -111,12 +111,8 @@ pub fn parse_capabilities( .map(|e| CAPABILITY_FILE_EXTENSIONS.contains(&e)) .unwrap_or_default() }) - // filter schema file - .filter(|p| { - p.file_name() - .map(|name| name != CAPABILITIES_SCHEMA_FILE_NAME) - .unwrap_or(true) - }) + // filter schema files + .filter(|p| p.parent().unwrap().file_name().unwrap() != CAPABILITIES_SCHEMA_FOLDER_NAME) { println!("cargo:rerun-if-changed={}", path.display()); @@ -219,7 +215,7 @@ pub fn generate_schema>( let schema_str = serde_json::to_string_pretty(&schema).unwrap(); let out_dir = out_dir.as_ref(); - create_dir_all(&out_dir).expect("unable to create schema output directory"); + create_dir_all(out_dir).expect("unable to create schema output directory"); let mut schema_file = BufWriter::new( File::create(out_dir.join(PERMISSION_SCHEMA_FILE_NAME)).map_err(Error::CreateFile)?, diff --git a/core/tauri-utils/src/platform.rs b/core/tauri-utils/src/platform.rs index 6659438b6097..b5648054dc50 100644 --- a/core/tauri-utils/src/platform.rs +++ b/core/tauri-utils/src/platform.rs @@ -4,7 +4,10 @@ //! Platform helper functions. -use std::path::{PathBuf, MAIN_SEPARATOR}; +use std::{ + fmt::Display, + path::{PathBuf, MAIN_SEPARATOR}, +}; use crate::{Env, PackageInfo}; @@ -25,6 +28,22 @@ pub enum Target { Ios, } +impl Display for Target { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + match self { + Self::Darwin => "darwin", + Self::Windows => "windows", + Self::Linux => "linux", + Self::Android => "android", + Self::Ios => "ios", + } + ) + } +} + impl Target { /// Parses the target from the given target triple. pub fn from_triple(target: &str) -> Self { diff --git a/core/tauri/src/command/authority.rs b/core/tauri/src/command/authority.rs index b6c15566bdf8..24701f53dd91 100644 --- a/core/tauri/src/command/authority.rs +++ b/core/tauri/src/command/authority.rs @@ -47,7 +47,7 @@ impl RuntimeAuthority { pub fn resolve_access( &self, command: &str, - window: &String, + window: &str, context: ExecutionContext, ) -> Option<&ResolvedCommand> { let key = CommandKey { diff --git a/examples/api/src-tauri/capabilities/.gitignore b/examples/api/src-tauri/capabilities/.gitignore index 9fe3b17f12ec..c75f615b12f1 100644 --- a/examples/api/src-tauri/capabilities/.gitignore +++ b/examples/api/src-tauri/capabilities/.gitignore @@ -1 +1 @@ -.schema.json +schemas/ diff --git a/examples/api/src-tauri/capabilities/run-app.json b/examples/api/src-tauri/capabilities/run-app.json new file mode 100644 index 000000000000..8052a8958e7b --- /dev/null +++ b/examples/api/src-tauri/capabilities/run-app.json @@ -0,0 +1,89 @@ +{ + "$schema": "./schemas/desktop-schema.json", + "identifier": "run-app", + "description": "permissions to run the app", + "windows": [ + "main", + "main-*" + ], + "permissions": [ + "path:default", + "event:default", + "window:default", + "app:default", + "resources:default", + "menu:default", + "tray:default", + "app:allow-app-hide", + "app:allow-app-show", + "window:allow-create", + "window:allow-center", + "window:allow-request-user-attention", + "window:allow-set-resizable", + "window:allow-set-maximizable", + "window:allow-set-minimizable", + "window:allow-set-closable", + "window:allow-set-title", + "window:allow-maximize", + "window:allow-unmaximize", + "window:allow-minimize", + "window:allow-unminimize", + "window:allow-show", + "window:allow-hide", + "window:allow-close", + "window:allow-set-decorations", + "window:allow-set-shadow", + "window:allow-set-effects", + "window:allow-set-always-on-top", + "window:allow-set-always-on-bottom", + "window:allow-set-content-protected", + "window:allow-set-size", + "window:allow-set-min-size", + "window:allow-set-max-size", + "window:allow-set-position", + "window:allow-set-fullscreen", + "window:allow-set-focus", + "window:allow-set-skip-taskbar", + "window:allow-set-cursor-grab", + "window:allow-set-cursor-visible", + "window:allow-set-cursor-icon", + "window:allow-set-cursor-position", + "window:allow-set-ignore-cursor-events", + "window:allow-start-dragging", + "window:allow-set-progress-bar", + "window:allow-print", + "window:allow-set-icon", + "window:allow-toggle-maximize", + "menu:allow-new", + "menu:allow-append", + "menu:allow-prepend", + "menu:allow-insert", + "menu:allow-remove", + "menu:allow-remove-at", + "menu:allow-items", + "menu:allow-get", + "menu:allow-popup", + "menu:allow-create-default", + "menu:allow-set-as-app-menu", + "menu:allow-set-as-window-menu", + "menu:allow-text", + "menu:allow-set-text", + "menu:allow-is-enabled", + "menu:allow-set-enabled", + "menu:allow-set-accelerator", + "menu:allow-set-as-windows-menu-for-nsapp", + "menu:allow-set-as-help-menu-for-nsapp", + "menu:allow-is-checked", + "menu:allow-set-checked", + "menu:allow-set-icon", + "tray:allow-new", + "tray:allow-set-icon", + "tray:allow-set-menu", + "tray:allow-set-tooltip", + "tray:allow-set-title", + "tray:allow-set-visible", + "tray:allow-set-temp-dir-path", + "tray:allow-set-icon-as-template", + "tray:allow-set-show-menu-on-left-click" + ] +} \ No newline at end of file diff --git a/examples/api/src-tauri/capabilities/run-app.toml b/examples/api/src-tauri/capabilities/run-app.toml deleted file mode 100644 index b61789625349..000000000000 --- a/examples/api/src-tauri/capabilities/run-app.toml +++ /dev/null @@ -1,88 +0,0 @@ -"$schema" = ".schema.json" -identifier = "run-app" -description = "app capability" -windows = ["main", "main-*"] -permissions = [ - "path:default", - "event:default", - "window:default", - "app:default", - "resources:default", - "menu:default", - "tray:default", - # app - "app:allow-app-hide", - "app:allow-app-show", - # window - "window:allow-create", - "window:allow-center", - "window:allow-request-user-attention", - "window:allow-set-resizable", - "window:allow-set-maximizable", - "window:allow-set-minimizable", - "window:allow-set-closable", - "window:allow-set-title", - "window:allow-maximize", - "window:allow-unmaximize", - "window:allow-minimize", - "window:allow-unminimize", - "window:allow-show", - "window:allow-hide", - "window:allow-close", - "window:allow-set-decorations", - "window:allow-set-shadow", - "window:allow-set-effects", - "window:allow-set-always-on-top", - "window:allow-set-always-on-bottom", - "window:allow-set-content-protected", - "window:allow-set-size", - "window:allow-set-min-size", - "window:allow-set-max-size", - "window:allow-set-position", - "window:allow-set-fullscreen", - "window:allow-set-focus", - "window:allow-set-skip-taskbar", - "window:allow-set-cursor-grab", - "window:allow-set-cursor-visible", - "window:allow-set-cursor-icon", - "window:allow-set-cursor-position", - "window:allow-set-ignore-cursor-events", - "window:allow-start-dragging", - "window:allow-set-progress-bar", - "window:allow-print", - "window:allow-set-icon", - "window:allow-toggle-maximize", - # menu - "menu:allow-new", - "menu:allow-append", - "menu:allow-prepend", - "menu:allow-insert", - "menu:allow-remove", - "menu:allow-remove-at", - "menu:allow-items", - "menu:allow-get", - "menu:allow-popup", - "menu:allow-create-default", - "menu:allow-set-as-app-menu", - "menu:allow-set-as-window-menu", - "menu:allow-text", - "menu:allow-set-text", - "menu:allow-is-enabled", - "menu:allow-set-enabled", - "menu:allow-set-accelerator", - "menu:allow-set-as-windows-menu-for-nsapp", - "menu:allow-set-as-help-menu-for-nsapp", - "menu:allow-is-checked", - "menu:allow-set-checked", - "menu:allow-set-icon", - # tray - "tray:allow-new", - "tray:allow-set-icon", - "tray:allow-set-menu", - "tray:allow-set-tooltip", - "tray:allow-set-title", - "tray:allow-set-visible", - "tray:allow-set-temp-dir-path", - "tray:allow-set-icon-as-template", - "tray:allow-set-show-menu-on-left-click", -] From 053ade4e7b0e9fe2a7016ddfb0886588aa96be33 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Thu, 18 Jan 2024 10:15:34 -0300 Subject: [PATCH 60/69] lint [skip ci] --- core/tauri-utils/src/acl/capability.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/core/tauri-utils/src/acl/capability.rs b/core/tauri-utils/src/acl/capability.rs index 8c620f419625..d586194f9d0f 100644 --- a/core/tauri-utils/src/acl/capability.rs +++ b/core/tauri-utils/src/acl/capability.rs @@ -72,14 +72,14 @@ pub enum CapabilityPlatform { impl CapabilityPlatform { /// Checks if the platform matches the given [`Target`]. pub fn matches(&self, target: &Target) -> bool { - match (self, target) { - (Self::Windows | Self::Desktop, Target::Windows) => true, - (Self::Linux | Self::Desktop, Target::Linux) => true, - (Self::MacOS | Self::Desktop, Target::Darwin) => true, - (Self::Android | Self::Mobile, Target::Android) => true, - (Self::Ios | Self::Mobile, Target::Ios) => true, - _ => false, - } + matches!( + (self, target), + (Self::Windows | Self::Desktop, Target::Windows) + | (Self::Linux | Self::Desktop, Target::Linux) + | (Self::MacOS | Self::Desktop, Target::Darwin) + | (Self::Android | Self::Mobile, Target::Android) + | (Self::Ios | Self::Mobile, Target::Ios) + ) } } From 4361330200e796273d0088b7c5cd2b3f3166eb5f Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Thu, 18 Jan 2024 15:48:32 -0300 Subject: [PATCH 61/69] rename allowlist build mod [skip ci] --- core/tauri-build/src/lib.rs | 4 ++-- core/tauri-build/src/{allowlist.rs => manifest.rs} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename core/tauri-build/src/{allowlist.rs => manifest.rs} (98%) diff --git a/core/tauri-build/src/lib.rs b/core/tauri-build/src/lib.rs index 02e6ec1e6a26..bae1942c5177 100644 --- a/core/tauri-build/src/lib.rs +++ b/core/tauri-build/src/lib.rs @@ -29,11 +29,11 @@ use std::{ }; mod acl; -mod allowlist; #[cfg(feature = "codegen")] mod codegen; /// Tauri configuration functions. pub mod config; +mod manifest; /// Mobile build functions. pub mod mobile; mod static_vcruntime; @@ -459,7 +459,7 @@ pub fn try_build(attributes: Attributes) -> Result<()> { let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap()); - allowlist::check(&config, &mut manifest)?; + manifest::check(&config, &mut manifest)?; let plugin_manifests = acl::get_plugin_manifests()?; std::fs::write( out_dir.join(PLUGIN_MANIFESTS_FILE_NAME), diff --git a/core/tauri-build/src/allowlist.rs b/core/tauri-build/src/manifest.rs similarity index 98% rename from core/tauri-build/src/allowlist.rs rename to core/tauri-build/src/manifest.rs index 8494a5abde47..afdebf554b3c 100644 --- a/core/tauri-build/src/allowlist.rs +++ b/core/tauri-build/src/manifest.rs @@ -211,7 +211,7 @@ mod tests { }, ), ] { - assert_eq!(super::features_diff(¤t, &expected), result); + assert_eq!(manifest::features_diff(¤t, &expected), result); } } } From be1f3a6de321bb1477001021d33227661accfe47 Mon Sep 17 00:00:00 2001 From: Chip Reed Date: Tue, 16 Jan 2024 17:22:26 -0800 Subject: [PATCH 62/69] check restricted visibility --- core/tauri-macros/src/command/wrapper.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/tauri-macros/src/command/wrapper.rs b/core/tauri-macros/src/command/wrapper.rs index 187507d0108e..4df148ffd28c 100644 --- a/core/tauri-macros/src/command/wrapper.rs +++ b/core/tauri-macros/src/command/wrapper.rs @@ -136,8 +136,8 @@ pub fn wrapper(attributes: TokenStream, item: TokenStream) -> TokenStream { // macros used with `pub use my_macro;` need to be exported with `#[macro_export]` let maybe_macro_export = match &function.vis { - Visibility::Public(_) => quote!(#[macro_export]), - _ => Default::default(), + Visibility::Public(_) | Visibility::Restricted(_) => quote!(#[macro_export]), + _ => TokenStream2::default(), }; let invoke = Invoke { From 8dd6ec180b2071b27e1a2d56318e3f24d11951d9 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Fri, 19 Jan 2024 09:43:54 -0300 Subject: [PATCH 63/69] simplify capability target [skip ci] --- core/tauri-build/src/acl.rs | 6 +--- core/tauri-codegen/src/context.rs | 4 +-- core/tauri-utils/src/acl/capability.rs | 49 +++++--------------------- core/tauri-utils/src/acl/resolved.rs | 6 +--- core/tauri-utils/src/config/parse.rs | 6 ++-- core/tauri-utils/src/platform.rs | 22 ++++++++---- 6 files changed, 32 insertions(+), 61 deletions(-) diff --git a/core/tauri-build/src/acl.rs b/core/tauri-build/src/acl.rs index 8bf627a70a68..86ea9e22a1e2 100644 --- a/core/tauri-build/src/acl.rs +++ b/core/tauri-build/src/acl.rs @@ -128,11 +128,7 @@ pub fn validate_capabilities( let target = tauri_utils::platform::Target::from_triple(&std::env::var("TARGET").unwrap()); for capability in capabilities.values() { - if !capability - .platforms - .iter() - .any(|platform| platform.matches(&target)) - { + if !capability.platforms.contains(&target) { continue; } diff --git a/core/tauri-codegen/src/context.rs b/core/tauri-codegen/src/context.rs index 559f6041f6b4..6e5aa26cc783 100644 --- a/core/tauri-codegen/src/context.rs +++ b/core/tauri-codegen/src/context.rs @@ -240,7 +240,7 @@ pub fn context_codegen(data: ContextData) -> Result Result, /// Target platforms this capability applies. By default all platforms applies. #[serde(default = "default_platforms")] - pub platforms: Vec, + pub platforms: Vec, } -fn default_platforms() -> Vec { - vec![CapabilityPlatform::Desktop, CapabilityPlatform::Mobile] -} - -/// Target platform of a capability. -#[derive(Debug, Clone, Serialize, Deserialize)] -#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] -#[serde(rename_all = "camelCase")] -pub enum CapabilityPlatform { - /// Windows. - Windows, - /// Linux. - Linux, - /// macOS. - #[serde(rename = "macOS")] - MacOS, - /// Android. - Android, - /// iOS - #[serde(rename = "iOS")] - Ios, - /// Desktop. - Desktop, - /// Mobile. - Mobile, -} - -impl CapabilityPlatform { - /// Checks if the platform matches the given [`Target`]. - pub fn matches(&self, target: &Target) -> bool { - matches!( - (self, target), - (Self::Windows | Self::Desktop, Target::Windows) - | (Self::Linux | Self::Desktop, Target::Linux) - | (Self::MacOS | Self::Desktop, Target::Darwin) - | (Self::Android | Self::Mobile, Target::Android) - | (Self::Ios | Self::Mobile, Target::Ios) - ) - } +fn default_platforms() -> Vec { + vec![ + Target::Linux, + Target::MacOS, + Target::Windows, + Target::Android, + Target::Ios, + ] } /// Context of the capability. diff --git a/core/tauri-utils/src/acl/resolved.rs b/core/tauri-utils/src/acl/resolved.rs index b9c0087e5896..07ad73a1f0aa 100644 --- a/core/tauri-utils/src/acl/resolved.rs +++ b/core/tauri-utils/src/acl/resolved.rs @@ -77,11 +77,7 @@ impl Resolved { // resolve commands for capability in capabilities.values() { - if !capability - .platforms - .iter() - .any(|platform| platform.matches(&target)) - { + if !capability.platforms.contains(&target) { continue; } diff --git a/core/tauri-utils/src/config/parse.rs b/core/tauri-utils/src/config/parse.rs index b098cb545707..d82c6a27edde 100644 --- a/core/tauri-utils/src/config/parse.rs +++ b/core/tauri-utils/src/config/parse.rs @@ -51,21 +51,21 @@ impl ConfigFormat { fn into_platform_file_name(self, target: Target) -> &'static str { match self { Self::Json => match target { - Target::Darwin => "tauri.macos.conf.json", + Target::MacOS => "tauri.macos.conf.json", Target::Windows => "tauri.windows.conf.json", Target::Linux => "tauri.linux.conf.json", Target::Android => "tauri.android.conf.json", Target::Ios => "tauri.ios.conf.json", }, Self::Json5 => match target { - Target::Darwin => "tauri.macos.conf.json5", + Target::MacOS => "tauri.macos.conf.json5", Target::Windows => "tauri.windows.conf.json5", Target::Linux => "tauri.linux.conf.json5", Target::Android => "tauri.android.conf.json5", Target::Ios => "tauri.ios.conf.json5", }, Self::Toml => match target { - Target::Darwin => "Tauri.macos.toml", + Target::MacOS => "Tauri.macos.toml", Target::Windows => "Tauri.windows.toml", Target::Linux => "Tauri.linux.toml", Target::Android => "Tauri.android.toml", diff --git a/core/tauri-utils/src/platform.rs b/core/tauri-utils/src/platform.rs index b5648054dc50..1ff29964b050 100644 --- a/core/tauri-utils/src/platform.rs +++ b/core/tauri-utils/src/platform.rs @@ -9,15 +9,20 @@ use std::{ path::{PathBuf, MAIN_SEPARATOR}, }; +use serde::{Deserialize, Serialize}; + use crate::{Env, PackageInfo}; mod starting_binary; /// Platform target. -#[derive(PartialEq, Eq, Copy, Clone)] +#[derive(PartialEq, Eq, Copy, Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] +#[serde(rename_all = "camelCase")] pub enum Target { /// MacOS. - Darwin, + #[serde(rename = "macOS")] + MacOS, /// Windows. Windows, /// Linux. @@ -25,6 +30,7 @@ pub enum Target { /// Android. Android, /// iOS. + #[serde(rename = "iOS")] Ios, } @@ -34,11 +40,11 @@ impl Display for Target { f, "{}", match self { - Self::Darwin => "darwin", + Self::MacOS => "macOS", Self::Windows => "windows", Self::Linux => "linux", Self::Android => "android", - Self::Ios => "ios", + Self::Ios => "iOS", } ) } @@ -48,7 +54,7 @@ impl Target { /// Parses the target from the given target triple. pub fn from_triple(target: &str) -> Self { if target.contains("darwin") { - Self::Darwin + Self::MacOS } else if target.contains("windows") { Self::Windows } else if target.contains("android") { @@ -63,9 +69,13 @@ impl Target { /// Gets the current build target. pub fn current() -> Self { if cfg!(target_os = "macos") { - Self::Darwin + Self::MacOS } else if cfg!(target_os = "windows") { Self::Windows + } else if cfg!(target_os = "ios") { + Self::Ios + } else if cfg!(target_os = "android") { + Self::Android } else { Self::Linux } From 1b29ff7e4798539573cf3031fa5aa885f44ea748 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Sat, 20 Jan 2024 08:11:08 -0300 Subject: [PATCH 64/69] hide codegen build behind tauri-build::try_run --- core/tauri-build/src/codegen/context.rs | 15 +-------------- core/tauri-build/src/lib.rs | 15 +++++++++++++++ examples/api/src-tauri/build.rs | 6 +++--- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/core/tauri-build/src/codegen/context.rs b/core/tauri-build/src/codegen/context.rs index e1991d206e74..5313ec5f86ff 100644 --- a/core/tauri-build/src/codegen/context.rs +++ b/core/tauri-build/src/codegen/context.rs @@ -78,20 +78,7 @@ impl CodegenContext { /// /// Unless you are doing something special with this builder, you don't need to do anything with /// the returned output path. - /// - /// # Panics - /// - /// If any parts of the codegen fail, this will panic with the related error message. This is - /// typically desirable when running inside a build script; see [`Self::try_build`] for no panics. - pub fn build(self) -> PathBuf { - match self.try_build() { - Ok(out) => out, - Err(error) => panic!("Error found during Codegen::build: {error}"), - } - } - - /// Non-panicking [`Self::build`] - pub fn try_build(self) -> Result { + pub(crate) fn try_build(self) -> Result { let (config, config_parent) = tauri_codegen::get_config(&self.config_path)?; // rerun if changed diff --git a/core/tauri-build/src/lib.rs b/core/tauri-build/src/lib.rs index bae1942c5177..227761d3c1c0 100644 --- a/core/tauri-build/src/lib.rs +++ b/core/tauri-build/src/lib.rs @@ -339,6 +339,8 @@ pub struct Attributes { #[allow(dead_code)] windows_attributes: WindowsAttributes, capabilities_path_pattern: Option<&'static str>, + #[cfg(feature = "codegen")] + codegen: Option, } impl Attributes { @@ -360,6 +362,14 @@ impl Attributes { self.capabilities_path_pattern.replace(pattern); self } + + #[cfg(feature = "codegen")] + #[cfg_attr(docsrs, doc(cfg(feature = "codegen")))] + #[must_use] + pub fn codegen(mut self, codegen: codegen::context::CodegenContext) -> Self { + self.codegen.replace(codegen); + self + } } /// Run all build time helpers for your Tauri Application. @@ -644,6 +654,11 @@ pub fn try_build(attributes: Attributes) -> Result<()> { } } + #[cfg(feature = "codegen")] + if let Some(codegen) = attributes.codegen { + codegen.try_build()?; + } + Ok(()) } diff --git a/examples/api/src-tauri/build.rs b/examples/api/src-tauri/build.rs index fb8781fe8079..e7b35e0b38c5 100644 --- a/examples/api/src-tauri/build.rs +++ b/examples/api/src-tauri/build.rs @@ -3,11 +3,11 @@ // SPDX-License-Identifier: MIT fn main() { - tauri_build::build(); - let mut codegen = tauri_build::CodegenContext::new(); if !cfg!(feature = "custom-protocol") { codegen = codegen.dev(); } - codegen.build(); + + tauri_build::try_build(tauri_build::Attributes::new().codegen(codegen)) + .expect("failed to run tauri-build"); } From 09909212654f1a362bf6457477e57ddd7e0bbb0e Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Sat, 20 Jan 2024 09:00:55 -0300 Subject: [PATCH 65/69] optimize build scripts [skip ci] --- core/tauri-build/src/lib.rs | 10 ++++++---- core/tauri-utils/src/acl/build.rs | 9 ++++++--- core/tauri/build.rs | 7 +++++-- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/core/tauri-build/src/lib.rs b/core/tauri-build/src/lib.rs index 227761d3c1c0..5aab858b5f4c 100644 --- a/core/tauri-build/src/lib.rs +++ b/core/tauri-build/src/lib.rs @@ -25,6 +25,7 @@ use tauri_utils::{ use std::{ env::var_os, + fs::read_to_string, path::{Path, PathBuf}, }; @@ -484,10 +485,11 @@ pub fn try_build(attributes: Attributes) -> Result<()> { acl::validate_capabilities(&plugin_manifests, &capabilities)?; - std::fs::write( - out_dir.join(CAPABILITIES_FILE_NAME), - serde_json::to_string(&capabilities)?, - )?; + let capabilities_path = out_dir.join(CAPABILITIES_FILE_NAME); + let capabilities_json = serde_json::to_string(&capabilities)?; + if capabilities_json != read_to_string(&capabilities_path).unwrap_or_default() { + std::fs::write(capabilities_path, capabilities_json)?; + } println!("cargo:rustc-env=TAURI_ENV_TARGET_TRIPLE={target_triple}"); diff --git a/core/tauri-utils/src/acl/build.rs b/core/tauri-utils/src/acl/build.rs index 5e4e854cd26a..9f001c29b34a 100644 --- a/core/tauri-utils/src/acl/build.rs +++ b/core/tauri-utils/src/acl/build.rs @@ -7,7 +7,7 @@ use std::{ collections::{BTreeMap, HashMap}, env::{current_dir, vars_os}, - fs::{create_dir_all, File}, + fs::{create_dir_all, read_to_string, File}, io::{BufWriter, Write}, path::{Path, PathBuf}, }; @@ -309,7 +309,10 @@ commands.deny = ["{command}"] schema_path = schema_path.display().to_string().replace('\\', "\\\\") ); - std::fs::write(path.join(format!("{command}.toml")), toml) - .unwrap_or_else(|_| panic!("unable to autogenerate ${command}.toml")); + let out_path = path.join(format!("{command}.toml")); + if toml != read_to_string(&out_path).unwrap_or_default() { + std::fs::write(out_path, toml) + .unwrap_or_else(|_| panic!("unable to autogenerate ${command}.toml")); + } } } diff --git a/core/tauri/build.rs b/core/tauri/build.rs index 5739c88f5d71..e944be71b76f 100644 --- a/core/tauri/build.rs +++ b/core/tauri/build.rs @@ -312,8 +312,11 @@ permissions = [{default_permissions}] "###, ); - std::fs::write(autogenerated.join("default.toml"), default_toml) - .unwrap_or_else(|_| panic!("unable to autogenerate default permissions")); + let out_path = autogenerated.join("default.toml"); + if default_toml != read_to_string(&out_path).unwrap_or_default() { + std::fs::write(out_path, default_toml) + .unwrap_or_else(|_| panic!("unable to autogenerate default permissions")); + } let permissions = tauri_utils::acl::build::define_permissions( &format!("./permissions/{plugin}/**/*.toml"), From 0ccc8b885237b29d4215de3bedaf2ab833240738 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Mon, 22 Jan 2024 18:16:31 -0300 Subject: [PATCH 66/69] fix tests --- core/tauri-build/src/manifest.rs | 2 +- .../acl_tests__tests__basic-ping.snap | 20 ++++++- ...cl_tests__tests__file-explorer-remote.snap | 39 +++++++++++- .../acl_tests__tests__file-explorer.snap | 39 +++++++++++- .../snapshots/acl_tests__tests__scope.snap | 59 +++++++++++++++++-- core/tests/acl/src/lib.rs | 8 ++- 6 files changed, 155 insertions(+), 12 deletions(-) diff --git a/core/tauri-build/src/manifest.rs b/core/tauri-build/src/manifest.rs index afdebf554b3c..f578d9fc80e0 100644 --- a/core/tauri-build/src/manifest.rs +++ b/core/tauri-build/src/manifest.rs @@ -211,7 +211,7 @@ mod tests { }, ), ] { - assert_eq!(manifest::features_diff(¤t, &expected), result); + assert_eq!(crate::manifest::features_diff(¤t, &expected), result); } } } diff --git a/core/tests/acl/fixtures/snapshots/acl_tests__tests__basic-ping.snap b/core/tests/acl/fixtures/snapshots/acl_tests__tests__basic-ping.snap index 51d739424052..68967415e8f7 100644 --- a/core/tests/acl/fixtures/snapshots/acl_tests__tests__basic-ping.snap +++ b/core/tests/acl/fixtures/snapshots/acl_tests__tests__basic-ping.snap @@ -1,5 +1,6 @@ --- source: core/tests/acl/src/lib.rs +assertion_line: 59 expression: resolved --- Resolved { @@ -9,7 +10,24 @@ Resolved { context: Local, }: ResolvedCommand { windows: [ - "main", + Pattern { + original: "main", + tokens: [ + Char( + 'm', + ), + Char( + 'a', + ), + Char( + 'i', + ), + Char( + 'n', + ), + ], + is_recursive: false, + }, ], scope: None, }, diff --git a/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer-remote.snap b/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer-remote.snap index d56cf57dee71..8215c1241f59 100644 --- a/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer-remote.snap +++ b/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer-remote.snap @@ -1,5 +1,6 @@ --- source: core/tests/acl/src/lib.rs +assertion_line: 59 expression: resolved --- Resolved { @@ -11,7 +12,24 @@ Resolved { }, }: ResolvedCommand { windows: [ - "main", + Pattern { + original: "main", + tokens: [ + Char( + 'm', + ), + Char( + 'a', + ), + Char( + 'i', + ), + Char( + 'n', + ), + ], + is_recursive: false, + }, ], scope: None, }, @@ -22,7 +40,24 @@ Resolved { }, }: ResolvedCommand { windows: [ - "main", + Pattern { + original: "main", + tokens: [ + Char( + 'm', + ), + Char( + 'a', + ), + Char( + 'i', + ), + Char( + 'n', + ), + ], + is_recursive: false, + }, ], scope: None, }, diff --git a/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer.snap b/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer.snap index a0382179e6c4..4fe88d56ac7f 100644 --- a/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer.snap +++ b/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer.snap @@ -1,5 +1,6 @@ --- source: core/tests/acl/src/lib.rs +assertion_line: 59 expression: resolved --- Resolved { @@ -9,7 +10,24 @@ Resolved { context: Local, }: ResolvedCommand { windows: [ - "main", + Pattern { + original: "main", + tokens: [ + Char( + 'm', + ), + Char( + 'a', + ), + Char( + 'i', + ), + Char( + 'n', + ), + ], + is_recursive: false, + }, ], scope: None, }, @@ -18,7 +36,24 @@ Resolved { context: Local, }: ResolvedCommand { windows: [ - "main", + Pattern { + original: "main", + tokens: [ + Char( + 'm', + ), + Char( + 'a', + ), + Char( + 'i', + ), + Char( + 'n', + ), + ], + is_recursive: false, + }, ], scope: None, }, diff --git a/core/tests/acl/fixtures/snapshots/acl_tests__tests__scope.snap b/core/tests/acl/fixtures/snapshots/acl_tests__tests__scope.snap index d50e511d15be..65ddec90897e 100644 --- a/core/tests/acl/fixtures/snapshots/acl_tests__tests__scope.snap +++ b/core/tests/acl/fixtures/snapshots/acl_tests__tests__scope.snap @@ -1,6 +1,6 @@ --- source: core/tests/acl/src/lib.rs -assertion_line: 49 +assertion_line: 59 expression: resolved --- Resolved { @@ -10,7 +10,24 @@ Resolved { context: Local, }: ResolvedCommand { windows: [ - "main", + Pattern { + original: "main", + tokens: [ + Char( + 'm', + ), + Char( + 'a', + ), + Char( + 'i', + ), + Char( + 'n', + ), + ], + is_recursive: false, + }, ], scope: Some( 18088007599891946824, @@ -21,7 +38,24 @@ Resolved { context: Local, }: ResolvedCommand { windows: [ - "main", + Pattern { + original: "main", + tokens: [ + Char( + 'm', + ), + Char( + 'a', + ), + Char( + 'i', + ), + Char( + 'n', + ), + ], + is_recursive: false, + }, ], scope: Some( 7912899488978770657, @@ -32,7 +66,24 @@ Resolved { context: Local, }: ResolvedCommand { windows: [ - "main", + Pattern { + original: "main", + tokens: [ + Char( + 'm', + ), + Char( + 'a', + ), + Char( + 'i', + ), + Char( + 'n', + ), + ], + is_recursive: false, + }, ], scope: Some( 7912899488978770657, diff --git a/core/tests/acl/src/lib.rs b/core/tests/acl/src/lib.rs index bf4d72adf112..25d899b4a33a 100644 --- a/core/tests/acl/src/lib.rs +++ b/core/tests/acl/src/lib.rs @@ -10,7 +10,10 @@ mod tests { path::Path, }; - use tauri_utils::acl::{build::parse_capabilities, plugin::Manifest, resolved::Resolved}; + use tauri_utils::{ + acl::{build::parse_capabilities, plugin::Manifest, resolved::Resolved}, + platform::Target, + }; fn load_plugins(plugins: &[String]) -> BTreeMap { let mut manifests = BTreeMap::new(); @@ -50,7 +53,8 @@ mod tests { let capabilities = parse_capabilities(&format!("{}/*.toml", fixture_entry.path().display())) .expect("failed to parse capabilities"); - let resolved = Resolved::resolve(manifests, capabilities).expect("failed to resolve ACL"); + let resolved = Resolved::resolve(manifests, capabilities, Target::current()) + .expect("failed to resolve ACL"); insta::assert_debug_snapshot!( fixture_entry From 65992eb2a529fc9fcc9128f3466762b167082c34 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Mon, 22 Jan 2024 18:30:19 -0300 Subject: [PATCH 67/69] tests for RuntimeAuthority::resolve_access --- core/tauri-utils/src/acl/mod.rs | 2 +- core/tauri-utils/src/acl/resolved.rs | 4 +- core/tauri/src/command/authority.rs | 148 +++++++++++++++++++++++++++ 3 files changed, 151 insertions(+), 3 deletions(-) diff --git a/core/tauri-utils/src/acl/mod.rs b/core/tauri-utils/src/acl/mod.rs index 1ab343afb4bb..fab6d6fa24ce 100644 --- a/core/tauri-utils/src/acl/mod.rs +++ b/core/tauri-utils/src/acl/mod.rs @@ -184,7 +184,7 @@ pub struct PermissionSet { } /// Execution context of an IPC call. -#[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)] pub enum ExecutionContext { /// A local URL is used (the Tauri app URL). Local, diff --git a/core/tauri-utils/src/acl/resolved.rs b/core/tauri-utils/src/acl/resolved.rs index 07ad73a1f0aa..cace7b24aae5 100644 --- a/core/tauri-utils/src/acl/resolved.rs +++ b/core/tauri-utils/src/acl/resolved.rs @@ -21,7 +21,7 @@ use super::{ pub type ScopeKey = usize; /// A resolved command permission. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct ResolvedCommand { /// The list of window label patterns that is allowed to run this command. pub windows: Vec, @@ -40,7 +40,7 @@ pub struct ResolvedScope { /// A command key for the map of allowed and denied commands. /// Takes into consideration the command name and the execution context. -#[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct CommandKey { /// The full command name. pub name: String, diff --git a/core/tauri/src/command/authority.rs b/core/tauri/src/command/authority.rs index 24701f53dd91..d46865375783 100644 --- a/core/tauri/src/command/authority.rs +++ b/core/tauri/src/command/authority.rs @@ -203,3 +203,151 @@ impl ScopeManager { } } } + +#[cfg(test)] +mod tests { + use glob::Pattern; + use tauri_utils::acl::{ + resolved::{CommandKey, Resolved, ResolvedCommand}, + ExecutionContext, + }; + + use super::RuntimeAuthority; + + #[test] + fn window_glob_pattern_matches() { + let command = CommandKey { + name: "my-command".into(), + context: ExecutionContext::Local, + }; + let window = "main-*"; + + let resolved_cmd = ResolvedCommand { + windows: vec![Pattern::new(window).unwrap()], + scope: None, + }; + let allowed_commands = [(command.clone(), resolved_cmd.clone())] + .into_iter() + .collect(); + + let authority = RuntimeAuthority::new(Resolved { + allowed_commands, + denied_commands: Default::default(), + command_scope: Default::default(), + global_scope: Default::default(), + }); + + assert_eq!( + authority.resolve_access( + &command.name, + &window.replace("*", "something"), + command.context + ), + Some(&resolved_cmd) + ); + } + + #[test] + fn remote_domain_matches() { + let command = CommandKey { + name: "my-command".into(), + context: ExecutionContext::Remote { + domain: "tauri.app".into(), + }, + }; + let window = "main"; + + let resolved_cmd = ResolvedCommand { + windows: vec![Pattern::new(window).unwrap()], + scope: None, + }; + let allowed_commands = [(command.clone(), resolved_cmd.clone())] + .into_iter() + .collect(); + + let authority = RuntimeAuthority::new(Resolved { + allowed_commands, + denied_commands: Default::default(), + command_scope: Default::default(), + global_scope: Default::default(), + }); + + assert_eq!( + authority.resolve_access(&command.name, window, command.context), + Some(&resolved_cmd) + ); + } + + #[test] + fn remote_context_denied() { + let command = CommandKey { + name: "my-command".into(), + context: ExecutionContext::Local, + }; + let window = "main"; + + let resolved_cmd = ResolvedCommand { + windows: vec![Pattern::new(window).unwrap()], + scope: None, + }; + let allowed_commands = [(command.clone(), resolved_cmd.clone())] + .into_iter() + .collect(); + + let authority = RuntimeAuthority::new(Resolved { + allowed_commands, + denied_commands: Default::default(), + command_scope: Default::default(), + global_scope: Default::default(), + }); + + assert!(authority + .resolve_access( + &command.name, + window, + ExecutionContext::Remote { + domain: "tauri.app".into() + } + ) + .is_none()); + } + + #[test] + fn denied_command_takes_precendence() { + let command = CommandKey { + name: "my-command".into(), + context: ExecutionContext::Local, + }; + let window = "main"; + let windows = vec![Pattern::new(window).unwrap()]; + let allowed_commands = [( + command.clone(), + ResolvedCommand { + windows: windows.clone(), + scope: None, + }, + )] + .into_iter() + .collect(); + let denied_commands = [( + command.clone(), + ResolvedCommand { + windows: windows.clone(), + scope: None, + }, + )] + .into_iter() + .collect(); + + let authority = RuntimeAuthority::new(Resolved { + allowed_commands, + denied_commands, + command_scope: Default::default(), + global_scope: Default::default(), + }); + + assert!(authority + .resolve_access(&command.name, window, command.context) + .is_none()); + } +} From 5eb1f7bd73ddbd21e413e6c34c1e5127f55e758f Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Mon, 22 Jan 2024 18:44:06 -0300 Subject: [PATCH 68/69] remote domain glob pattern --- core/tauri-utils/src/acl/capability.rs | 2 +- core/tauri-utils/src/acl/mod.rs | 11 +- core/tauri-utils/src/acl/resolved.rs | 5 +- core/tauri/src/command/authority.rs | 99 ++++++- core/tauri/src/command/mod.rs | 2 +- core/tauri/src/window/mod.rs | 7 +- ...cl_tests__tests__file-explorer-remote.snap | 68 ++++- examples/api/src-tauri/Cargo.lock | 278 +++++++++++++++++- 8 files changed, 433 insertions(+), 39 deletions(-) diff --git a/core/tauri-utils/src/acl/capability.rs b/core/tauri-utils/src/acl/capability.rs index 4823a3dd2a4d..5d163175ed7f 100644 --- a/core/tauri-utils/src/acl/capability.rs +++ b/core/tauri-utils/src/acl/capability.rs @@ -62,7 +62,7 @@ pub enum CapabilityContext { Local, /// Capability refers to remote usage. Remote { - /// Remote domains this capability refers to. + /// Remote domains this capability refers to. Can use glob patterns. domains: Vec, }, } diff --git a/core/tauri-utils/src/acl/mod.rs b/core/tauri-utils/src/acl/mod.rs index fab6d6fa24ce..350eb93e704e 100644 --- a/core/tauri-utils/src/acl/mod.rs +++ b/core/tauri-utils/src/acl/mod.rs @@ -4,6 +4,7 @@ //! Access Control List types. +use glob::Pattern; use serde::{Deserialize, Serialize}; use std::num::NonZeroU64; use thiserror::Error; @@ -190,15 +191,13 @@ pub enum ExecutionContext { Local, /// Remote URL is tring to use the IPC. Remote { - /// The domain trying to access the IPC. - domain: String, + /// The domain trying to access the IPC (glob pattern). + domain: Pattern, }, } #[cfg(feature = "build")] mod build_ { - use crate::tokens::*; - use super::*; use proc_macro2::TokenStream; use quote::{quote, ToTokens, TokenStreamExt}; @@ -212,8 +211,8 @@ mod build_ { quote! { #prefix::Local } } Self::Remote { domain } => { - let domain = str_lit(domain); - quote! { #prefix::Remote { domain: #domain } } + let domain = domain.as_str(); + quote! { #prefix::Remote { domain: #domain.parse().unwrap() } } } }); } diff --git a/core/tauri-utils/src/acl/resolved.rs b/core/tauri-utils/src/acl/resolved.rs index cace7b24aae5..40224b7a632a 100644 --- a/core/tauri-utils/src/acl/resolved.rs +++ b/core/tauri-utils/src/acl/resolved.rs @@ -9,6 +9,8 @@ use std::{ hash::{Hash, Hasher}, }; +use glob::Pattern; + use crate::platform::Target; use super::{ @@ -233,7 +235,8 @@ fn resolve_command( CapabilityContext::Remote { domains } => domains .iter() .map(|domain| ExecutionContext::Remote { - domain: domain.to_string(), + domain: Pattern::new(domain) + .unwrap_or_else(|e| panic!("invalid glob pattern for remote domain {domain}: {e}")), }) .collect(), }; diff --git a/core/tauri/src/command/authority.rs b/core/tauri/src/command/authority.rs index d46865375783..06cf86f9e648 100644 --- a/core/tauri/src/command/authority.rs +++ b/core/tauri/src/command/authority.rs @@ -24,6 +24,32 @@ pub struct RuntimeAuthority { scope_manager: ScopeManager, } +/// The origin trying to access the IPC. +pub enum Origin { + /// Local app origin. + Local, + /// Remote origin. + Remote { + /// Remote origin domain. + domain: String, + }, +} + +impl Origin { + fn matches(&self, context: &ExecutionContext) -> bool { + match (self, context) { + (Self::Local, ExecutionContext::Local) => true, + ( + Self::Remote { domain }, + ExecutionContext::Remote { + domain: domain_pattern, + }, + ) => domain_pattern.matches(domain), + _ => false, + } + } +} + impl RuntimeAuthority { pub(crate) fn new(acl: Resolved) -> Self { let command_cache = acl @@ -48,18 +74,20 @@ impl RuntimeAuthority { &self, command: &str, window: &str, - context: ExecutionContext, + origin: Origin, ) -> Option<&ResolvedCommand> { - let key = CommandKey { - name: command.into(), - context, - }; - if self.denied_commands.contains_key(&key) { + if self + .denied_commands + .keys() + .any(|cmd| cmd.name == command && origin.matches(&cmd.context)) + { None } else { self .allowed_commands - .get(&key) + .iter() + .find(|(cmd, _)| cmd.name == command && origin.matches(&cmd.context)) + .map(|(_cmd, allowed)| allowed) .filter(|allowed| allowed.windows.iter().any(|w| w.matches(window))) } } @@ -212,6 +240,8 @@ mod tests { ExecutionContext, }; + use crate::command::Origin; + use super::RuntimeAuthority; #[test] @@ -241,7 +271,7 @@ mod tests { authority.resolve_access( &command.name, &window.replace("*", "something"), - command.context + Origin::Local ), Some(&resolved_cmd) ); @@ -249,10 +279,11 @@ mod tests { #[test] fn remote_domain_matches() { + let domain = "tauri.app"; let command = CommandKey { name: "my-command".into(), context: ExecutionContext::Remote { - domain: "tauri.app".into(), + domain: Pattern::new(domain).unwrap(), }, }; let window = "main"; @@ -273,7 +304,51 @@ mod tests { }); assert_eq!( - authority.resolve_access(&command.name, window, command.context), + authority.resolve_access( + &command.name, + window, + Origin::Remote { + domain: domain.into() + } + ), + Some(&resolved_cmd) + ); + } + + #[test] + fn remote_domain_glob_pattern_matches() { + let domain = "tauri.*"; + let command = CommandKey { + name: "my-command".into(), + context: ExecutionContext::Remote { + domain: Pattern::new(domain).unwrap(), + }, + }; + let window = "main"; + + let resolved_cmd = ResolvedCommand { + windows: vec![Pattern::new(window).unwrap()], + scope: None, + }; + let allowed_commands = [(command.clone(), resolved_cmd.clone())] + .into_iter() + .collect(); + + let authority = RuntimeAuthority::new(Resolved { + allowed_commands, + denied_commands: Default::default(), + command_scope: Default::default(), + global_scope: Default::default(), + }); + + assert_eq!( + authority.resolve_access( + &command.name, + window, + Origin::Remote { + domain: domain.replace("*", "studio") + } + ), Some(&resolved_cmd) ); } @@ -305,7 +380,7 @@ mod tests { .resolve_access( &command.name, window, - ExecutionContext::Remote { + Origin::Remote { domain: "tauri.app".into() } ) @@ -347,7 +422,7 @@ mod tests { }); assert!(authority - .resolve_access(&command.name, window, command.context) + .resolve_access(&command.name, window, Origin::Local) .is_none()); } } diff --git a/core/tauri/src/command/mod.rs b/core/tauri/src/command/mod.rs index 8fae0dd60300..7a0296356ecd 100644 --- a/core/tauri/src/command/mod.rs +++ b/core/tauri/src/command/mod.rs @@ -18,7 +18,7 @@ use serde::{ mod authority; -pub use authority::{CommandScope, GlobalScope, RuntimeAuthority}; +pub use authority::{CommandScope, GlobalScope, Origin, RuntimeAuthority}; use tauri_utils::acl::resolved::ResolvedCommand; /// Represents a custom command. diff --git a/core/tauri/src/window/mod.rs b/core/tauri/src/window/mod.rs index 92d52a2113a9..d566e0e3fcce 100644 --- a/core/tauri/src/window/mod.rs +++ b/core/tauri/src/window/mod.rs @@ -9,7 +9,6 @@ pub(crate) mod plugin; use http::HeaderMap; pub use tauri_runtime::window::PageLoadEvent; use tauri_runtime::ResizeDirection; -use tauri_utils::acl::ExecutionContext; pub use tauri_utils::{config::Color, WindowEffect as Effect, WindowEffectState as EffectState}; use url::Url; @@ -17,7 +16,7 @@ use url::Url; use crate::TitleBarStyle; use crate::{ app::{AppHandle, UriSchemeResponder}, - command::{CommandArg, CommandItem}, + command::{CommandArg, CommandItem, Origin}, event::{EmitArgs, Event, EventId}, ipc::{ CallbackFn, Invoke, InvokeBody, InvokeError, InvokeMessage, InvokeResolver, @@ -2351,9 +2350,9 @@ impl Window { &request.cmd, &message.window.window.label, if is_local { - ExecutionContext::Local + Origin::Local } else { - ExecutionContext::Remote { + Origin::Remote { domain: current_url .domain() .map(|d| d.to_string()) diff --git a/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer-remote.snap b/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer-remote.snap index 8215c1241f59..d3a474292c89 100644 --- a/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer-remote.snap +++ b/core/tests/acl/fixtures/snapshots/acl_tests__tests__file-explorer-remote.snap @@ -8,7 +8,39 @@ Resolved { CommandKey { name: "plugin:fs|read_dir", context: Remote { - domain: "tauri.app", + domain: Pattern { + original: "tauri.app", + tokens: [ + Char( + 't', + ), + Char( + 'a', + ), + Char( + 'u', + ), + Char( + 'r', + ), + Char( + 'i', + ), + Char( + '.', + ), + Char( + 'a', + ), + Char( + 'p', + ), + Char( + 'p', + ), + ], + is_recursive: false, + }, }, }: ResolvedCommand { windows: [ @@ -36,7 +68,39 @@ Resolved { CommandKey { name: "plugin:fs|read_file", context: Remote { - domain: "tauri.app", + domain: Pattern { + original: "tauri.app", + tokens: [ + Char( + 't', + ), + Char( + 'a', + ), + Char( + 'u', + ), + Char( + 'r', + ), + Char( + 'i', + ), + Char( + '.', + ), + Char( + 'a', + ), + Char( + 'p', + ), + Char( + 'p', + ), + ], + is_recursive: false, + }, }, }: ResolvedCommand { windows: [ diff --git a/examples/api/src-tauri/Cargo.lock b/examples/api/src-tauri/Cargo.lock index a03a6953651b..8bd15757cd0d 100644 --- a/examples/api/src-tauri/Cargo.lock +++ b/examples/api/src-tauri/Cargo.lock @@ -160,6 +160,12 @@ dependencies = [ "window-shadows", ] +[[package]] +name = "as-raw-xcb-connection" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" + [[package]] name = "ascii" version = "1.1.0" @@ -470,6 +476,20 @@ name = "bytemuck" version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] [[package]] name = "byteorder" @@ -964,6 +984,56 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading 0.7.4", +] + +[[package]] +name = "downcast-rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" + +[[package]] +name = "drm" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb1b703ffbc7ebd216eba7900008049a56ace55580ecb2ee7fa801e8d8be87" +dependencies = [ + "bitflags 2.4.1", + "bytemuck", + "drm-ffi", + "drm-fourcc", + "nix 0.27.1", +] + +[[package]] +name = "drm-ffi" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba7d1c19c4b6270e89d59fb27dc6d02a317c658a8a54e54781e1db9b5947595d" +dependencies = [ + "drm-sys", + "nix 0.27.1", +] + +[[package]] +name = "drm-fourcc" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aafbcdb8afc29c1a7ee5fbe53b5d62f4565b35a042a662ca9fecd0b54dae6f4" + +[[package]] +name = "drm-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a4f1c0468062a56cd5705f1e3b5409eb286d5596a2028ec8e947595d7e715ae" + [[package]] name = "dtoa" version = "1.0.9" @@ -1407,6 +1477,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "gethostname" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb65d4ba3173c56a500b555b532f72c42e8d1fe64962b518897f8959fae2c177" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "getrandom" version = "0.1.16" @@ -1976,7 +2056,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf" dependencies = [ "gtk-sys", - "libloading", + "libloading 0.7.4", "once_cell", ] @@ -1996,6 +2076,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "libloading" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "line-wrap" version = "0.1.1" @@ -2098,6 +2188,15 @@ version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +[[package]] +name = "memmap2" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45fd3a57831bf88bc63f8cebc0cf956116276e97fef3966103e96416209f7c92" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.7.1" @@ -2171,7 +2270,7 @@ dependencies = [ "jni-sys", "ndk-sys", "num_enum", - "raw-window-handle", + "raw-window-handle 0.5.2", "thiserror", ] @@ -2208,6 +2307,17 @@ dependencies = [ "memoffset 0.7.1", ] +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.4.1", + "cfg-if", + "libc", +] + [[package]] name = "nodrop" version = "0.1.14" @@ -2582,7 +2692,7 @@ dependencies = [ "base64", "indexmap 1.9.3", "line-wrap", - "quick-xml", + "quick-xml 0.29.0", "serde", "time", ] @@ -2718,6 +2828,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "quick-xml" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" +dependencies = [ + "memchr", +] + [[package]] name = "quote" version = "1.0.35" @@ -2814,6 +2933,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" +[[package]] +name = "raw-window-handle" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42a9830a0e1b9fb145ebb365b8bc4ccd75f290f98c0247deafbbe2c75cefb544" + [[package]] name = "redox_syscall" version = "0.2.16" @@ -3281,6 +3406,37 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "softbuffer" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa97594e034a52bfc0f7a2764f0445bd6dcf1c27136779b244473f9c24f9c5e" +dependencies = [ + "as-raw-xcb-connection", + "bytemuck", + "cfg_aliases", + "cocoa", + "core-graphics", + "drm", + "fastrand 2.0.1", + "foreign-types", + "js-sys", + "log", + "memmap2", + "objc", + "raw-window-handle 0.6.0", + "redox_syscall 0.4.1", + "rustix 0.38.21", + "tiny-xlib", + "wasm-bindgen", + "wayland-backend", + "wayland-client", + "wayland-sys", + "web-sys", + "windows-sys 0.48.0", + "x11rb", +] + [[package]] name = "soup3" version = "0.5.0" @@ -3462,7 +3618,8 @@ dependencies = [ "once_cell", "parking_lot", "png", - "raw-window-handle", + "raw-window-handle 0.5.2", + "raw-window-handle 0.6.0", "scopeguard", "tao-macros", "unicode-segmentation", @@ -3517,7 +3674,7 @@ dependencies = [ "objc", "percent-encoding", "png", - "raw-window-handle", + "raw-window-handle 0.5.2", "reqwest", "serde", "serde_json", @@ -3647,7 +3804,7 @@ dependencies = [ "gtk", "http", "jni", - "raw-window-handle", + "raw-window-handle 0.5.2", "serde", "serde_json", "tauri-utils", @@ -3665,7 +3822,8 @@ dependencies = [ "http", "jni", "percent-encoding", - "raw-window-handle", + "raw-window-handle 0.5.2", + "softbuffer", "tao", "tauri-runtime", "tauri-utils", @@ -3807,6 +3965,18 @@ dependencies = [ "time-core", ] +[[package]] +name = "tiny-xlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4098d49269baa034a8d1eae9bd63e9fa532148d772121dace3bcd6a6c98eb6d" +dependencies = [ + "as-raw-xcb-connection", + "ctor", + "libloading 0.8.1", + "tracing", +] + [[package]] name = "tiny_http" version = "0.11.0" @@ -4266,6 +4436,55 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wayland-backend" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19152ddd73f45f024ed4534d9ca2594e0ef252c1847695255dae47f34df9fbe4" +dependencies = [ + "cc", + "downcast-rs", + "nix 0.26.4", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ca7d52347346f5473bf2f56705f360e8440873052e575e55890c4fa57843ed3" +dependencies = [ + "bitflags 2.4.1", + "nix 0.26.4", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb8e28403665c9f9513202b7e1ed71ec56fde5c107816843fb14057910b2c09c" +dependencies = [ + "proc-macro2", + "quick-xml 0.30.0", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15a0c8eaff5216d07f226cb7a549159267f3467b289d9a2e52fd3ef5aae2b7af" +dependencies = [ + "dlib", + "log", + "once_cell", + "pkg-config", +] + [[package]] name = "web-sys" version = "0.3.64" @@ -4381,6 +4600,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "winapi-wsapoll" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -4395,7 +4623,7 @@ checksum = "67ff424735b1ac21293b0492b069394b0a189c8a463fb015a16dea7c2e221c08" dependencies = [ "cocoa", "objc", - "raw-window-handle", + "raw-window-handle 0.5.2", "windows-sys 0.48.0", ] @@ -4407,7 +4635,7 @@ checksum = "5931735e675b972fada30c7a402915d4d827aa5ef6c929c133d640c4b785e963" dependencies = [ "cocoa", "objc", - "raw-window-handle", + "raw-window-handle 0.5.2", "windows-sys 0.48.0", ] @@ -4736,7 +4964,7 @@ dependencies = [ "objc", "objc_id", "once_cell", - "raw-window-handle", + "raw-window-handle 0.5.2", "serde", "serde_json", "sha2", @@ -4774,13 +5002,39 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "x11rb" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1641b26d4dec61337c35a1b1aaf9e3cba8f46f0b43636c609ab0291a648040a" +dependencies = [ + "as-raw-xcb-connection", + "gethostname", + "libc", + "libloading 0.7.4", + "nix 0.26.4", + "once_cell", + "winapi", + "winapi-wsapoll", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82d6c3f9a0fb6701fab8f6cea9b0c0bd5d6876f1f89f7fada07e558077c344bc" +dependencies = [ + "nix 0.26.4", +] + [[package]] name = "xdg-home" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2769203cd13a0c6015d515be729c526d041e9cf2c0cc478d57faee85f40c6dcd" dependencies = [ - "nix", + "nix 0.26.4", "winapi", ] @@ -4808,7 +5062,7 @@ dependencies = [ "futures-sink", "futures-util", "hex", - "nix", + "nix 0.26.4", "once_cell", "ordered-stream", "rand 0.8.5", From 69abd206f64af8c9e4e1f8bf415adafcf63d09ad Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Mon, 22 Jan 2024 21:03:03 -0300 Subject: [PATCH 69/69] lint --- core/tauri/src/command/authority.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/tauri/src/command/authority.rs b/core/tauri/src/command/authority.rs index 06cf86f9e648..b7e28c719342 100644 --- a/core/tauri/src/command/authority.rs +++ b/core/tauri/src/command/authority.rs @@ -270,7 +270,7 @@ mod tests { assert_eq!( authority.resolve_access( &command.name, - &window.replace("*", "something"), + &window.replace('*', "something"), Origin::Local ), Some(&resolved_cmd) @@ -346,7 +346,7 @@ mod tests { &command.name, window, Origin::Remote { - domain: domain.replace("*", "studio") + domain: domain.replace('*', "studio") } ), Some(&resolved_cmd)