---
title: プラグイン・アクセス権の記述
sidebar:
  order: 11
i18nReady: true
---

import { Steps } from '@astrojs/starlight/components';
import ShowSolution from '@components/ShowSolution.astro';
import Cta from '@fragments/cta.mdx';
import TranslationNote from '@components/i18n/TranslationNote.astro';

この章での演習目的は、自分自身でプラグインを記述する際の、プラグイン・アクセス権をどのように作成するかをより深く理解することです。

演習の終わりには、自分のプラグインに簡単なアクセス権を設定できる能力が身についていることでしょう。
アクセス権が部分的に自動生成と手作業とで作成される Tauri プラグインの例を示します。

<Steps>

1. ### Tauri プラグインの作成

   この例では、Tauri [`cli`](/reference/cli/)〔英語サイト〕を利用して Tauri プラグインのソース・コード構造体をブートストラップ（起動）します。
   すべての[必要事項](/ja/start/prerequisites/)がインストールされているかを点検し、`cargo tauri info` を実行して Tauri CLI が正しいバージョンであることを確認してください。

   出力結果には、`tauri-cli` のバージョンが「`2.x`」であることが示されるはずです。
   このステップ別の説明手順では `pnpm` を使用して進めていきますが、別のパッケージ・マネージャーも選択可能です。選択したパッケージ・マネージャーに応じてコマンドを置き換えてください。

   最新バージョンのインストールが行なわれていれば、Tauri CLI を使用してプラグインの作成を開始できます。

    {/* prettier-ignore */}
    <ShowSolution>
    ```sh
    mkdir -p tauri-learning
    cd tauri-learning
    cargo tauri plugin new test
    cd tauri-plugin-test
    pnpm install
    pnpm build
    cargo build
    ```
    </ShowSolution>
    
2. ### 新しいコマンドの作成

    実用的でシンプルな例をお見せするために、コマンドがユーザー入力を一時フォルダー内のファイルに書き込み、そのファイルにカスタム・ヘッダーを追加する処理を想定しましょう。

    このコマンドに「`write_custom_file`」という名前を付け、「`src/commands.rs`」に実装し、プラグイン・ビルダーに追加してフロントエンドに公開します。

    Tauri のコア・ユーティリティはこのコマンドの `allow`（許可）および `deny`（拒否）権限を自動生成するため、このアクセス権について考慮する必要はありません。

    <ShowSolution>

    コマンドの実装：（以下の最後の部分が「`write_custome_file`」コマンドを追加している箇所）

    ```rust title="src/commands.rs" ins={15-22} ins=", Manager"
    use tauri::{AppHandle, command, Runtime};

    use crate::models::*;
    use crate::Result;
    use crate::TestExt;

    #[command]
    pub(crate) async fn ping<R: Runtime>(
        app: AppHandle<R>,
        payload: PingRequest,
    ) -> Result<PingResponse> {
        app.test1().ping(payload)
    }

    #[command]
    pub(crate) async fn write_custom_file<R: Runtime>(
        user_input: String,
        app: AppHandle<R>,
    ) -> Result<String> {
        std::fs::write(app.path().temp_dir().unwrap(), user_input)?;
        Ok("success".to_string())
    }

    ```

    新しいコマンドに組み込みアクセス権限を自動生成します：

    ```rust title="src/build.rs" ins=""write_custom_file""
    const COMMANDS: &[&str] = &["ping", "write_custom_file"];
    ```

    このような組み込みアクセス権限は Tauri ビルド・システムによって自動的に生成され、`permissions/autogenerated/commands` フォルダーに表示されます。
    デフォルトでは、`enable-<command>`（〇〇を許可）および `deny-<command>`（〇〇を拒否）のアクセス権限が作成されます。

    </ShowSolution>

3. ### 新しいコマンドの公開

   「ステップ 2」は、実際のコマンド実装を記述するためのものでした。
   つづいて、そのコマンドをフロントエンドに公開して使用できるようにします。

   <ShowSolution>

   新たに実装したコマンドにフロントエンド IPC 要求を渡すための「呼び出しハンドラー」を生成するように Tauri ビルダーを設定します：

   ```rust title="src/lib.rs"  ins="commands::write_custom_file,"
   pub fn init<R: Runtime>() -> TauriPlugin<R> {
   Builder::new("test")
       .invoke_handler(tauri::generate_handler![
           commands::ping,
           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）
           app.manage(MyState::default());
           Ok(())
       })
       .build()
   }
   ```

   フロントエンド・モジュールに新しいコマンドを公開します。

   このステップは、このサンプル・アプリケーションがフロントエンド・モジュールを正常にインポートするために不可欠です。
   この処理は便宜上のものであり、セキュリティへの影響はありません。というのも、コマンド・ハンドラーがすでに生成されており、コマンドをフロントエンドから手動で呼び出すことができるためです。

   ```ts title="guest-js/index.ts" ins={11-13}
   import { invoke } from '@tauri-apps/api/core';

   export async function ping(value: string): Promise<string | null> {
     return await invoke<{ value?: string }>('plugin:test|ping', {
       payload: {
         value,
       },
     }).then((r) => (r.value ? r.value : null));
   }

   export async function writeCustomFile(user_input: string): Promise<string> {
     return await invoke('plugin:test|write_custom_file', {
       userInput: user_input,
     });
   }
   ```

   :::tip
   呼び出しパラメータは「キャメルケース CamelCase」（結合する単語の語頭を大文字）で記述する必要があります。この例では、「`user_input`」ではなく「`userInput`」という書き方になります。
   :::

   自分のパッケージがビルドされることを確認します：

   ```
   pnpm build
   ```

   </ShowSolution>

4. ### デフォルトのプラグイン・アクセス権を定義

    このプラグイン例ではデフォルトで `write_custom_file` コマンドを公開する必要があるため、このコマンドを `default.toml` のアクセス権限（permissions）に追加する必要があります。

    <ShowSolution>

    先ほど公開した新しいコマンドを許可するために、このコマンドをデフォルトのアクセス権限のセットに追加します。

    ```toml title="permissions/default.toml" ins=", "allow-write-custom-file""
    "$schema" = "schemas/schema.json"
    [default]
    description = "Default permissions for the plugin"
    permissions = ["allow-ping", "allow-write-custom-file"]
    ```

    </ShowSolution>

5. ### サンプル・アプリケーションからテスト・コマンドを呼び出す

    作成されたプラグイン・ディレクトリ構造には `examples/tauri-app` フォルダーがあり、そこにはプラグインをテストするためにすぐに使用できる Tauri アプリケーションが含まれています。

    新しいコマンドを追加したので、その新しいコマンドを呼び出すようにフロントエンドを少し変更する必要があります。

    <ShowSolution>

    ```svelte title="src/App.svelte" del={11-13,42-45} ins={14-16,45-49}
    <script>
      import Greet from './lib/Greet.svelte'
      import { ping, writeCustomFile } from 'tauri-plugin-test-api'

      let response = ''

      function updateResponse(returnValue) {
        response += `[${new Date().toLocaleTimeString()}]` + (typeof returnValue === 'string' ? returnValue : JSON.stringify(returnValue)) + '<br>'
      }

      function _ping() {
        ping("Pong!").then(updateResponse).catch(updateResponse)
      }
      function _writeCustomFile() {
        writeCustomFile("HELLO FROM TAURI PLUGIN").then(updateResponse).catch(updateResponse)
      }
    </script>

    <main class="container">
      <h1>Welcome to Tauri!</h1>

      <div class="row">
        <a href="https://vitejs.dev" target="_blank">
          <img src="/vite.svg" class="logo vite" alt="Vite Logo" />
        </a>
        <a href="https://tauri.app" target="_blank">
          <img src="/tauri.svg" class="logo tauri" alt="Tauri Logo" />
        </a>
        <a href="https://svelte.dev" target="_blank">
          <img src="/svelte.svg" class="logo svelte" alt="Svelte Logo" />
        </a>
      </div>

      <p>
        Click on the Tauri, Vite, and Svelte logos to learn more.
      </p>

      <div class="row">
        <Greet />
      </div>

      <div>
        <button on:click="{_ping}">Ping</button>
        <div>{@html response}</div>
      </div>
      <div>
        <button on:click="{_writeCustomFile}">Write</button>
        <div>{@html response}</div>
      </div>


    </main>

    <style>
      .logo.vite:hover {
        filter: drop-shadow(0 0 2em #747bff);
      }

      .logo.svelte:hover {
        filter: drop-shadow(0 0 2em #ff3e00);
      }
    </style>
    ```

    これを実行して「書き込み」ボタンを押すと、次のような画面が表示されるはずです：

    ```

    success　（成功）

    ```

    仮フォルダーには、新しく実装されたプラグイン・コマンドからのメッセージが含まれている `test.txt` ファイルができているはずです。
    🥳

    </ShowSolution>

 </Steps>

<div style="text-align: right;">
  【※ この日本語版は、「Feb 22, 2025 英語版」に基づいています】
</div>
