|
2 | 2 | // SPDX-License-Identifier: Apache-2.0
|
3 | 3 | // SPDX-License-Identifier: MIT
|
4 | 4 |
|
| 5 | +use std::path::PathBuf; |
| 6 | + |
| 7 | +use schemars::JsonSchema; |
| 8 | + |
5 | 9 | #[path = "src/scope_entry.rs"]
|
6 | 10 | mod scope_entry;
|
7 | 11 |
|
| 12 | +/// A command argument allowed to be executed by the webview API. |
| 13 | +#[derive(Debug, PartialEq, Eq, Clone, Hash, schemars::JsonSchema)] |
| 14 | +#[serde(untagged, deny_unknown_fields)] |
| 15 | +#[non_exhaustive] |
| 16 | +pub enum ShellScopeEntryAllowedArg { |
| 17 | + /// A non-configurable argument that is passed to the command in the order it was specified. |
| 18 | + Fixed(String), |
| 19 | + |
| 20 | + /// A variable that is set while calling the command from the webview API. |
| 21 | + /// |
| 22 | + Var { |
| 23 | + /// [regex] validator to require passed values to conform to an expected input. |
| 24 | + /// |
| 25 | + /// This will require the argument value passed to this variable to match the `validator` regex |
| 26 | + /// before it will be executed. |
| 27 | + /// |
| 28 | + /// The regex string is by default surrounded by `^...$` to match the full string. |
| 29 | + /// For example the `https?://\w+` regex would be registered as `^https?://\w+$`. |
| 30 | + /// |
| 31 | + /// [regex]: <https://docs.rs/regex/latest/regex/#syntax> |
| 32 | + validator: String, |
| 33 | + |
| 34 | + /// Marks the validator as a raw regex, meaning the plugin should not make any modification at runtime. |
| 35 | + /// |
| 36 | + /// This means the regex will not match on the entire string by default, which might |
| 37 | + /// be exploited if your regex allow unexpected input to be considered valid. |
| 38 | + /// When using this option, make sure your regex is correct. |
| 39 | + #[serde(default)] |
| 40 | + raw: bool, |
| 41 | + }, |
| 42 | +} |
| 43 | + |
| 44 | +/// A set of command arguments allowed to be executed by the webview API. |
| 45 | +/// |
| 46 | +/// A value of `true` will allow any arguments to be passed to the command. `false` will disable all |
| 47 | +/// arguments. A list of [`ShellScopeEntryAllowedArg`] will set those arguments as the only valid arguments to |
| 48 | +/// be passed to the attached command configuration. |
| 49 | +#[derive(Debug, PartialEq, Eq, Clone, Hash, JsonSchema)] |
| 50 | +#[serde(untagged, deny_unknown_fields)] |
| 51 | +#[non_exhaustive] |
| 52 | +pub enum ShellScopeEntryAllowedArgs { |
| 53 | + /// Use a simple boolean to allow all or disable all arguments to this command configuration. |
| 54 | + Flag(bool), |
| 55 | + |
| 56 | + /// A specific set of [`ShellScopeEntryAllowedArg`] that are valid to call for the command configuration. |
| 57 | + List(Vec<ShellScopeEntryAllowedArg>), |
| 58 | +} |
| 59 | + |
| 60 | +impl Default for ShellScopeEntryAllowedArgs { |
| 61 | + fn default() -> Self { |
| 62 | + Self::Flag(false) |
| 63 | + } |
| 64 | +} |
| 65 | + |
| 66 | +/// Shell scope entry. |
| 67 | +#[derive(JsonSchema)] |
| 68 | +#[serde(untagged, deny_unknown_fields)] |
| 69 | +#[allow(unused)] |
| 70 | +pub(crate) enum ShellScopeEntry { |
| 71 | + Command { |
| 72 | + /// The name for this allowed shell command configuration. |
| 73 | + /// |
| 74 | + /// This name will be used inside of the webview API to call this command along with |
| 75 | + /// any specified arguments. |
| 76 | + name: String, |
| 77 | + /// The command name. |
| 78 | + /// It can start with a variable that resolves to a system base directory. |
| 79 | + /// The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, |
| 80 | + /// `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, |
| 81 | + /// `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, |
| 82 | + /// `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`. |
| 83 | + // use default just so the schema doesn't flag it as required |
| 84 | + #[serde(rename = "cmd")] |
| 85 | + command: PathBuf, |
| 86 | + /// The allowed arguments for the command execution. |
| 87 | + #[serde(default)] |
| 88 | + args: ShellScopeEntryAllowedArgs, |
| 89 | + }, |
| 90 | + Sidecar { |
| 91 | + /// The name for this allowed shell command configuration. |
| 92 | + /// |
| 93 | + /// This name will be used inside of the webview API to call this command along with |
| 94 | + /// any specified arguments. |
| 95 | + name: String, |
| 96 | + /// The allowed arguments for the command execution. |
| 97 | + #[serde(default)] |
| 98 | + args: ShellScopeEntryAllowedArgs, |
| 99 | + /// If this command is a sidecar command. |
| 100 | + sidecar: bool, |
| 101 | + }, |
| 102 | +} |
| 103 | + |
| 104 | +// Ensure `ShellScopeEntry` and `scope_entry::EntryRaw` |
| 105 | +// and `ShellScopeEntryAllowedArg` and `ShellAllowedArg` |
| 106 | +// and `ShellScopeEntryAllowedArgs` and `ShellAllowedArgs` |
| 107 | +// are kept in sync |
| 108 | +#[allow(clippy::unnecessary_operation)] |
| 109 | +fn _f() { |
| 110 | + match (ShellScopeEntry::Sidecar { |
| 111 | + name: String::new(), |
| 112 | + args: ShellScopeEntryAllowedArgs::Flag(false), |
| 113 | + sidecar: true, |
| 114 | + }) { |
| 115 | + ShellScopeEntry::Command { |
| 116 | + name, |
| 117 | + command, |
| 118 | + args, |
| 119 | + } => scope_entry::EntryRaw { |
| 120 | + name, |
| 121 | + command: Some(command), |
| 122 | + args: match args { |
| 123 | + ShellScopeEntryAllowedArgs::Flag(flag) => scope_entry::ShellAllowedArgs::Flag(flag), |
| 124 | + ShellScopeEntryAllowedArgs::List(vec) => scope_entry::ShellAllowedArgs::List( |
| 125 | + vec.into_iter() |
| 126 | + .map(|s| match s { |
| 127 | + ShellScopeEntryAllowedArg::Fixed(fixed) => { |
| 128 | + scope_entry::ShellAllowedArg::Fixed(fixed) |
| 129 | + } |
| 130 | + ShellScopeEntryAllowedArg::Var { validator, raw } => { |
| 131 | + scope_entry::ShellAllowedArg::Var { validator, raw } |
| 132 | + } |
| 133 | + }) |
| 134 | + .collect(), |
| 135 | + ), |
| 136 | + }, |
| 137 | + sidecar: false, |
| 138 | + }, |
| 139 | + ShellScopeEntry::Sidecar { |
| 140 | + name, |
| 141 | + args, |
| 142 | + sidecar, |
| 143 | + } => scope_entry::EntryRaw { |
| 144 | + name, |
| 145 | + command: None, |
| 146 | + args: match args { |
| 147 | + ShellScopeEntryAllowedArgs::Flag(flag) => scope_entry::ShellAllowedArgs::Flag(flag), |
| 148 | + ShellScopeEntryAllowedArgs::List(vec) => scope_entry::ShellAllowedArgs::List( |
| 149 | + vec.into_iter() |
| 150 | + .map(|s| match s { |
| 151 | + ShellScopeEntryAllowedArg::Fixed(fixed) => { |
| 152 | + scope_entry::ShellAllowedArg::Fixed(fixed) |
| 153 | + } |
| 154 | + ShellScopeEntryAllowedArg::Var { validator, raw } => { |
| 155 | + scope_entry::ShellAllowedArg::Var { validator, raw } |
| 156 | + } |
| 157 | + }) |
| 158 | + .collect(), |
| 159 | + ), |
| 160 | + }, |
| 161 | + sidecar, |
| 162 | + }, |
| 163 | + }; |
| 164 | +} |
| 165 | + |
8 | 166 | const COMMANDS: &[&str] = &["execute", "spawn", "stdin_write", "kill", "open"];
|
9 | 167 |
|
10 | 168 | fn main() {
|
11 | 169 | tauri_plugin::Builder::new(COMMANDS)
|
12 | 170 | .global_api_script_path("./api-iife.js")
|
13 |
| - .global_scope_schema(schemars::schema_for!(scope_entry::Entry)) |
| 171 | + .global_scope_schema(schemars::schema_for!(ShellScopeEntry)) |
14 | 172 | .android_path("android")
|
15 | 173 | .ios_path("ios")
|
16 | 174 | .build();
|
|
0 commit comments