+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/content/docs/learn/Security/using-plugin-permissions.mdx b/src/content/docs/learn/Security/using-plugin-permissions.mdx
new file mode 100644
index 0000000000..37e48bf5c5
--- /dev/null
+++ b/src/content/docs/learn/Security/using-plugin-permissions.mdx
@@ -0,0 +1,292 @@
+---
+title: Using Plugin Permissions
+sidebar:
+ badge:
+ text: WIP
+---
+
+import { Steps } from '@astrojs/starlight/components';
+import ShowSolution from '@components/ShowSolution.astro'
+import Cta from '@fragments/cta.mdx';
+
+The goal of this excercise is to get a better understanding on how
+plugin permissions can be enabled or disabled, where they are described
+and how to use default permissions of plugins.
+
+At the end you will have the ability to find and use permissions of
+arbitrary plugins and understand how to custom tailor existing permissions.
+You will have an example Tauri application where a plugin and plugin specific
+permissions are used.
+
+
+
+1. ### Create Tauri Application
+
+ Create your Tauri application.
+ In our example we will facilitate [`create-tauri-app`](https://github.com/tauri-apps/create-tauri-app):
+
+
+
+ We will proceed in this step-by-step explanation with `pnpm` but you can choose another
+ package manager and replace it in the commands accordingly.
+
+
+
+ ```
+ pnpm create tauri-app
+ ```
+
+ ```
+ ✔ Project name · plugin-permission-demo
+ ✔ Choose which language to use for your frontend · TypeScript / JavaScript - (pnpm, yarn, npm, bun)
+ ✔ Choose your package manager · pnpm
+ ✔ Choose your UI template · Vanilla
+ ✔ Choose your UI flavor · TypeScript
+
+ Template created! To get started run:
+ cd plugin-permission-demo
+ pnpm install
+ pnpm tauri dev
+ ```
+
+
+2. ### Add the `file-system` Plugin to Your Application
+
+ To search for existing plugins you can use multiple resources.
+
+ The most straight forward way would be to check out if your plugin is already
+ in the [Plugins](/plugin/) section of the documentation and therefore part of Tauri's
+ maintained plugin set.
+ The Filesystem plugin is part of the Tauri plugin workspace and you can add it to
+ your project by following the [instructions](/plugin/file-system/#setup).
+
+ If the plugin is part of the community effort you can most likely find it
+ on [crates.io](https://crates.io/search?q=tauri-plugin-) when searching for `tauri-plugin-`.
+
+
+ If it is an existing plugin from our workspace you can use the automated way:
+
+ ```
+ pnpm tauri add fs
+ ```
+
+ If you have found it on [crates.io](https://crates.io/crates/tauri-plugin-fs)
+ you need to manually add it as a dependency and modify the Tauri builder
+ to initialize the plugin:
+
+ ```
+ cargo add tauri-plugin-fs
+ ```
+
+ Modify `lib.rs` to initialize the plugin:
+
+ ```rust title="src-tauri/src/lib.rs" ins={4}
+ #[cfg_attr(mobile, tauri::mobile_entry_point)]
+ fn run() {
+ tauri::Builder::default()
+ .plugin(tauri_plugin_fs::init())
+ .run(tauri::generate_context!())
+ .expect("error while running tauri application");
+ }
+ ```
+
+
+3. ### Understand the Default Permissions of the `fs` Plugin
+
+ Each plugin has a `default` permission set, which contains
+ all permissions and scopes to use the plugin out of the box
+ with a reasonable minimal feature set.
+
+ In the case of official maintained plugins you can find a
+ rendered description in the documentation
+ (eg. [fs default](/plugin/file-system/#default-permissions)).
+
+ In case you are figuring this out for a community plugin you
+ need to check out the source code of the plugin.
+ This should be defined in `your-plugin/permissions/default.toml`.
+
+
+ ```
+ "$schema" = "schemas/schema.json"
+
+ [default]
+ description = """
+ # Tauri `fs` default permissions
+
+ This configuration file defines the default permissions granted
+ to the filesystem.
+
+ ### Granted Permissions
+
+ This default permission set enables all read-related commands and
+ allows access to the `$APP` folder and sub directories created in it.
+ The location of the `$APP` folder depends on the operating system,
+ where the application is run.
+
+ In general the `$APP` folder needs to be manually created
+ by the application at runtime, before accessing files or folders
+ in it is possible.
+
+ ### Denied Permissions
+
+ This default permission set prevents access to critical components
+ of the Tauri application by default.
+ On Windows the webview data folder access is denied.
+
+ """
+ permissions = ["read-all", "scope-app-recursive", "deny-default"]
+
+ ```
+
+
+ 4. ### Find the Right Permissions
+
+ This step is all about finding the permissions you need to
+ for your commands to be exposed to the frontend with the minimal
+ access to your system.
+
+ The `fs` plugin has autogenerated permissions which will disable
+ or enable individual commands and allow or disable global scopes.
+
+ These can be found in the [documentation](/plugin/file-system/#command-permissions)
+ or in the source code of the plugin (`fs/permissions/autogenerated`).
+
+ Let us assume we want to enable writing to a text file `test.txt`
+ located in the users `$HOME` folder.
+
+ For this we would search in the autogenerated permissions for a
+ permission to enable writing to text files like `allow-write-text-file`
+ and then for a scope which would allow us to access the `$HOME/test.txt`
+ file.
+
+ We need to add these to our `capabilities` section in our
+ `src-tauri/tauri.conf.json` or in a file in the `src-tauri/capabilities/` folder.
+ By default there is already a capability in `src-tauri/capabilities/main.json` we
+ can modify.
+
+
+
+ ```json title="src-tauri/capabilities/default.json" del={18} ins={19}
+ {
+ "$schema": "../gen/schemas/desktop-schema.json",
+ "identifier": "default",
+ "description": "Capability for the main window",
+ "windows": [
+ "main"
+ ],
+ "permissions": [
+ "path:default",
+ "event:default",
+ "window:default",
+ "app:default",
+ "image:default",
+ "resources:default",
+ "menu:default",
+ "tray:default",
+ "shell:allow-open",
+ "fs:default",
+ "fs:allow-write-text-file",
+ ]
+ }
+ ```
+
+
+
+ Since there are only autogenerated scopes in the `fs` plugin to
+ access the full `$HOME` folder, we need to configure our own scope.
+ This scope should be only enabled for the `write-text-file` command
+ and should only expose our `test.txt` file.
+
+
+ ```json title="src-tauri/capabilities/default.json" del={18} ins={19-22}
+ {
+ "$schema": "../gen/schemas/desktop-schema.json",
+ "identifier": "default",
+ "description": "Capability for the main window",
+ "windows": [
+ "main"
+ ],
+ "permissions": [
+ "path:default",
+ "event:default",
+ "window:default",
+ "app:default",
+ "image:default",
+ "resources:default",
+ "menu:default",
+ "tray:default",
+ "shell:allow-open",
+ "fs:allow-write-text-file",
+ {
+ "identifier": "fs:allow-write-text-file",
+ "allow": [{ "path": "$HOME/test.txt" }]
+ },
+ ]
+ }
+ ```
+
+ 5. ### Test Permissions in Practice
+
+ After we have added the necessary permission we want to
+ confirm that our application can access the file and write
+ it's content.
+
+
+ We can use this snippet in our application to write to the file:
+
+ ```ts title="src/main.ts"
+ import { writeTextFile, BaseDirectory } from '@tauri-apps/plugin-fs';
+
+ let greetInputEl: HTMLInputElement | null;
+
+ async function write(message: string) {
+ await writeTextFile('test.txt', message, { baseDir: BaseDirectory.Home });
+ }
+
+ window.addEventListener("DOMContentLoaded", () => {
+ greetInputEl = document.querySelector("#greet-input");
+ document.querySelector("#greet-form")?.addEventListener("submit", (e) => {
+ e.preventDefault();
+ if (!greetInputEl )
+ return;
+
+ write(greetInputEl.value == "" ? "No input provided": greetInputEl.value);
+
+ });
+ });
+
+ ```
+
+ Replacing the `src/main.ts` with this snippet means we do not need to modify the default `index.html`,
+ when using the plain Vanilla+Typescript app.
+ Entering any input into the input field of the running app will be
+ written to the file on submit.
+
+ Let's test now in practice:
+
+ ```
+ pnpm run tauri dev
+ ```
+
+ After writing into the input and clicking "Submit",
+ we can check via our terminal emulator or by manually opening the
+ file in your home folder.
+
+ ```
+ cat $HOME/test.txt
+ ```
+
+ You should be presented with your input and finished learning about using permissions from plugins in Tauri applications.
+ 🥳
+
+
+ If you encountered this error:
+
+ ```sh
+ [Error] Unhandled Promise Rejection: fs.write_text_file not allowed. Permissions associated with this command: fs:allow-app-write, fs:allow-app-write-recursive, fs:allow-appcache-write, fs:allow-appcache-write-recursive, fs:allow-appconf...
+ (anonymous function) (main.ts:5)
+ ```
+ Then you very likely did not properly follow the [previous instructions](#find-the-right-permissions).
+
+
+
From f803020945003e2ac8b54c056232378092f9d0d5 Mon Sep 17 00:00:00 2001
From: Tillmann <112912081+tillmann-crabnebula@users.noreply.github.com>
Date: Mon, 10 Jun 2024 16:11:15 +0900
Subject: [PATCH 2/8] Iinitial guide to plugin command with permissions
---
.../Security/writing-plugin-permissions.mdx | 311 ++++++++++++++++++
1 file changed, 311 insertions(+)
create mode 100644 src/content/docs/learn/Security/writing-plugin-permissions.mdx
diff --git a/src/content/docs/learn/Security/writing-plugin-permissions.mdx b/src/content/docs/learn/Security/writing-plugin-permissions.mdx
new file mode 100644
index 0000000000..18feadebe8
--- /dev/null
+++ b/src/content/docs/learn/Security/writing-plugin-permissions.mdx
@@ -0,0 +1,311 @@
+---
+title: Writing Plugin Permissions
+sidebar:
+ badge:
+ text: WIP
+---
+
+import { Steps } from '@astrojs/starlight/components';
+import ShowSolution from '@components/ShowSolution.astro'
+import Cta from '@fragments/cta.mdx';
+
+The goal of this excercise is to get a better understanding on how
+plugin permissions can be created when writing your own plugin.
+
+At the end you will have the ability to create simple permissions for
+your plugins.
+You will have an example Tauri plugin where permissions are partially autogenerated
+and hand crafted.
+
+
+
+1. ### Create a Tauri Plugin
+
+ In our example we will facilitate the Tauri [`cli`]()
+ to bootstrap a Tauri plugin source code structure.
+ Make sure you have installed all [Prerequisites]()
+ and verify you have the Tauri CLI in the correct version
+ by running `cargo tauri info`.
+
+ The output should indicate the `tauri-cli` version is `2.x`.
+ We will proceed in this step-by-step explanation with `pnpm` but you can choose another
+ package manager and replace it in the commands accordingly.
+
+ Once you have a recent version installed you can go
+ ahead and create the plugin using the Tauri CLI.
+
+
+ ```sh
+ mkdir -p tauri-learning
+ cd tauri-learning
+ cargo tauri plugin new test
+ cd tauri-plugin-test
+ pnpm install
+ pnpm build
+ cargo build
+ ```
+
+
+2. ### Create a New Command
+
+ To showcase something practical and simple let us assume
+ our command writes user input to a file in our temporary folder while
+ adding some custom header to the file.
+
+ Let's name our command `write_custom_file`, implement it in `src/commands.rs`
+ and add it to our plugin builder to be exposed to the frontend.
+
+ Tauri's core utils will autogenerate `allow` and `deny` permissions for this
+ command, so we do not need to care about this.
+
+
+
+ The command implementation:
+
+ ```rust title="src/commands.rs" ins={15-22} ins=", Manager"
+ use tauri::{command, AppHandle, Runtime, State, Window, Manager};
+
+ use crate::{MyState, Result};
+
+ #[command]
+ pub(crate) async fn execute(
+ _app: AppHandle,
+ _window: Window,
+ state: State<'_, MyState>,
+ ) -> Result {
+ state.0.lock().unwrap().insert("key".into(), "value".into());
+ Ok("success".to_string())
+ }
+
+ #[command]
+ pub(crate) async fn write_custom_file(
+ user_input: String,
+ app: AppHandle,
+ ) -> Result {
+ std::fs::write(app.path().temp_dir().unwrap(), user_input)?;
+ Ok("success".to_string())
+ }
+
+ ```
+
+ Auto-Generate inbuilt permissions for your new command:
+
+ ```rust title="src/build.rs" ins="\"write_custom_file\""
+ const COMMANDS: &[&str] = &["ping", "execute", "write_custom_file"];
+ ```
+
+ These inbuilt permissions will be automatically generated by the Tauri build
+ system and will be visible in the `permissions/autogenerated/commands` folder.
+ By default an `enable-` and `deny-` permission will
+ be created.
+
+
+3. ### Expose the New Command
+
+ The previous step was to write the actual command implementation.
+ Next we want to expose it to the frontend so it can be consumed.
+
+
+
+ Configure the Tauri builder to generate the invoke handler to pass frontend
+ IPC requests to the newly implemented command:
+
+ ```rust title="src/lib.rs" ins="commands::write_custom_file,"
+ pub fn init() -> TauriPlugin {
+ Builder::new("test")
+ .invoke_handler(tauri::generate_handler![
+ commands::execute,
+ commands::write_custom_file,
+ ])
+ .setup(|app, api| {
+ #[cfg(mobile)]
+ let test = mobile::init(app, api)?;
+ #[cfg(desktop)]
+ let test = desktop::init(app, api)?;
+ app.manage(test);
+
+ // manage state so it is accessible by the commands
+ app.manage(MyState::default());
+ Ok(())
+ })
+ .build()
+ }
+ ```
+
+ Expose the new command in the frontend module:
+
+ :::note
+
+ This step is essential for the example application to sucessfully
+ import the frontend module but as soon as the command handler is generated
+ the command can be manually invoked from the frontend.
+
+ :::
+
+ ```ts title="guest-js/index.ts" ins={6-9}
+ import { invoke } from '@tauri-apps/api/core'
+
+ export async function execute() {
+ await invoke('plugin:test|execute')
+ }
+
+ export async function writeCustomFile(user_input: string): Promise {
+ return await invoke('plugin:test|write_custom_file',{userInput: user_input});
+ }
+ ```
+
+ :::tip
+ The invoke parameter needs to be CamelCase. In this example it is `userInput` instead of `user_input`.
+ :::
+
+ Make sure your package is built:
+
+ ```
+ pnpm build
+ ```
+
+
+
+4. ### Define Default Plugin Permissions
+
+ As our plugin should expose the `write_custom_file` command by default
+ we should add this to our `default.toml` permission.
+
+
+ Create a new default permission file if not already existing:
+ ```
+ touch permissions/default.toml
+ ```
+
+ Add this to our default permission set to allow the new command
+ we just exposed.
+
+ ```toml title="permissions/default.toml"
+ "$schema" = "schemas/schema.json"
+
+ [default]
+ description = """
+ This is the default permission set of our test plugin.
+ It enables the `write_custom_file` command to be exposed.
+ """
+ permissions = ["allow-write-custom-file"]
+ ```
+
+
+5. ### Invoke Test Command from Example Application
+
+ The created plugin directory structure contains an `example/tauri-app` folder,
+ which has a ready to use Tauri application to test out the plugin.
+
+ Since we added a new command we need to slightly modify the frontend to
+ invoke our new command instead.
+
+
+ ```svelte del={11-13,42-45} ins={14-16,45-49}
+
+
+
+
+ Click on the Tauri, Vite, and Svelte logos to learn more.
+
+
+
+
+
+
+
+
+
{@html response}
+
+
+
+
{@html response}
+
+
+
+
+
+
+ ```
+
+ Running this and trying to invoke the "Write" button will result in:
+
+ ```
+ test.execute not allowed. Permissions associated with this command: test:allow-execute
+ ```
+
+ Since this error already contains which permission is associated
+ we now know that have not added our default permission to the capability of the test
+ application.
+
+ ```json title="src-tauri/capabilities/main.json" ins={15}
+ {
+ "$schema": "../gen/schemas/desktop-schema.json",
+ "identifier": "main-capability",
+ "description": "Capability for the main window",
+ "windows": ["main"],
+ "permissions": [
+ "path:default",
+ "event:default",
+ "window:default",
+ "app:default",
+ "resources:default",
+ "menu:default",
+ "tray:default",
+ "window:allow-set-title",
+ "test:default"
+ ]
+ }
+ ```
+
+ Afterwards you should be greeted with this:
+
+ ```
+ success
+ ```
+
+ And you should find a `test.txt` file in your temporary folder containing a message
+ from our new implemented plugin command.
+ 🥳
+
+
+
+
From 962b96be35d4b40d628a03a67d5f96f334207972 Mon Sep 17 00:00:00 2001
From: Tillmann <112912081+tillmann-crabnebula@users.noreply.github.com>
Date: Mon, 10 Jun 2024 16:33:33 +0900
Subject: [PATCH 3/8] type and minor fixes
---
.../Security/writing-plugin-permissions.mdx | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/src/content/docs/learn/Security/writing-plugin-permissions.mdx b/src/content/docs/learn/Security/writing-plugin-permissions.mdx
index 18feadebe8..efc84df798 100644
--- a/src/content/docs/learn/Security/writing-plugin-permissions.mdx
+++ b/src/content/docs/learn/Security/writing-plugin-permissions.mdx
@@ -132,15 +132,12 @@ and hand crafted.
}
```
- Expose the new command in the frontend module:
-
- :::note
+ Expose the new command in the frontend module.
This step is essential for the example application to sucessfully
- import the frontend module but as soon as the command handler is generated
- the command can be manually invoked from the frontend.
-
- :::
+ import the frontend module. This is for convenience and has
+ no security impact, as the command handler is already generated
+ and the command can be manually invoked from the frontend.
```ts title="guest-js/index.ts" ins={6-9}
import { invoke } from '@tauri-apps/api/core'
@@ -194,14 +191,14 @@ and hand crafted.
5. ### Invoke Test Command from Example Application
- The created plugin directory structure contains an `example/tauri-app` folder,
+ The created plugin directory structure contains an `examples/tauri-app` folder,
which has a ready to use Tauri application to test out the plugin.
Since we added a new command we need to slightly modify the frontend to
invoke our new command instead.
- ```svelte del={11-13,42-45} ins={14-16,45-49}
+ ```svelte title="src/App.svelte" del={11-13,42-45} ins={14-16,45-49}