Skip to content

Commit 0bb7b0f

Browse files
feat: Add option to generate default permissions for inlined plugins (#10559)
* feat: Add option to allow all commands by default * option to use a list of permissions, move logic to tauri-build * fix plugin * add utils change file --------- Co-authored-by: Lucas Nogueira <lucas@tauri.app>
1 parent 213c0b1 commit 0bb7b0f

5 files changed

Lines changed: 103 additions & 6 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri-build": patch:feat
3+
---
4+
5+
Added `InlinedPlugin::default_permission` to autogenerate the default permission of an inlined plugin.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri-utils": patch:enhance
3+
---
4+
5+
Return autogenerated permissions from `autogenerate_command_permissions`.

core/tauri-build/src/acl.rs

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,19 @@ const ACL_MANIFESTS_FILE_NAME: &str = "acl-manifests.json";
4242
pub struct InlinedPlugin {
4343
commands: &'static [&'static str],
4444
permissions_path_pattern: Option<&'static str>,
45+
default: Option<DefaultPermissionRule>,
46+
}
47+
48+
/// Variants of a generated default permission that can be used on an [`InlinedPlugin`].
49+
#[derive(Debug)]
50+
pub enum DefaultPermissionRule {
51+
/// Allow all commands from [`InlinedPlugin::commands`].
52+
AllowAllCommands,
53+
/// Allow the given list of permissions.
54+
///
55+
/// Note that the list refers to permissions instead of command names,
56+
/// so for example a command called `execute` would need to be allowed as `allow-execute`.
57+
Allow(Vec<String>),
4558
}
4659

4760
impl InlinedPlugin {
@@ -65,6 +78,14 @@ impl InlinedPlugin {
6578
self.permissions_path_pattern.replace(pattern);
6679
self
6780
}
81+
82+
/// Creates a default permission for the plugin using the given rule.
83+
///
84+
/// Alternatively you can pull a permission in the filesystem in the permissions directory, see [`Self::permissions_path_pattern`].
85+
pub fn default_permission(mut self, default: DefaultPermissionRule) -> Self {
86+
self.default.replace(default);
87+
self
88+
}
6889
}
6990

7091
/// Tauri application permission manifest.
@@ -337,12 +358,35 @@ pub fn inline_plugins(
337358
let mut permission_files = if plugin.commands.is_empty() {
338359
Vec::new()
339360
} else {
340-
tauri_utils::acl::build::autogenerate_command_permissions(
361+
let autogenerated = tauri_utils::acl::build::autogenerate_command_permissions(
341362
&plugin_out_dir,
342363
plugin.commands,
343364
"",
344365
false,
345366
);
367+
368+
let default_permissions = plugin.default.map(|default| match default {
369+
DefaultPermissionRule::AllowAllCommands => autogenerated.allowed,
370+
DefaultPermissionRule::Allow(permissions) => permissions,
371+
});
372+
if let Some(default_permissions) = default_permissions {
373+
let default_permission_toml = format!(
374+
r###"# Automatically generated - DO NOT EDIT!
375+
[default]
376+
permissions = [{default_permissions}]
377+
"###,
378+
default_permissions = default_permissions
379+
.iter()
380+
.map(|p| format!("\"{p}\""))
381+
.collect::<Vec<String>>()
382+
.join(",")
383+
);
384+
385+
let default_permission_toml_path = plugin_out_dir.join("default.toml");
386+
387+
write_if_changed(&default_permission_toml, &default_permission_toml_path);
388+
}
389+
346390
tauri_utils::acl::build::define_permissions(
347391
&plugin_out_dir.join("*").to_string_lossy(),
348392
name,
@@ -384,6 +428,12 @@ pub fn inline_plugins(
384428
Ok(acl_manifests)
385429
}
386430

431+
fn write_if_changed(content: &str, path: &Path) {
432+
if content != read_to_string(path).unwrap_or_default() {
433+
std::fs::write(path, content).unwrap_or_else(|_| panic!("unable to autogenerate {path:?}"));
434+
}
435+
}
436+
387437
pub fn app_manifest_permissions(
388438
out_dir: &Path,
389439
manifest: AppManifest,

core/tauri-build/src/lib.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,17 @@ impl Attributes {
373373
self
374374
}
375375

376+
/// Adds the given list of plugins to the list of inlined plugins (a plugin that is part of your application).
377+
///
378+
/// See [`InlinedPlugin`] for more information.
379+
pub fn plugins<I>(mut self, plugins: I) -> Self
380+
where
381+
I: IntoIterator<Item = (&'static str, InlinedPlugin)>,
382+
{
383+
self.inlined_plugins.extend(plugins);
384+
self
385+
}
386+
376387
/// Sets the application manifest for the Access Control List.
377388
///
378389
/// See [`AppManifest`] for more information.

core/tauri-utils/src/acl/build.rs

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -388,13 +388,21 @@ fn parse_permissions(paths: Vec<PathBuf>) -> Result<Vec<PermissionFile>, Error>
388388
Ok(permissions)
389389
}
390390

391+
/// Permissions that are generated from commands using [`autogenerate_command_permissions`].
392+
pub struct AutogeneratedPermissions {
393+
/// The allow permissions generated from commands.
394+
pub allowed: Vec<String>,
395+
/// The deny permissions generated from commands.
396+
pub denied: Vec<String>,
397+
}
398+
391399
/// Autogenerate permission files for a list of commands.
392400
pub fn autogenerate_command_permissions(
393401
path: &Path,
394402
commands: &[&str],
395403
license_header: &str,
396404
schema_ref: bool,
397-
) {
405+
) -> AutogeneratedPermissions {
398406
if !path.exists() {
399407
create_dir_all(path).expect("unable to create autogenerated commands dir");
400408
}
@@ -418,8 +426,14 @@ pub fn autogenerate_command_permissions(
418426
"".to_string()
419427
};
420428

429+
let mut autogenerated = AutogeneratedPermissions {
430+
allowed: Vec::new(),
431+
denied: Vec::new(),
432+
};
433+
421434
for command in commands {
422435
let slugified_command = command.replace('_', "-");
436+
423437
let toml = format!(
424438
r###"{license_header}# Automatically generated - DO NOT EDIT!
425439
{schema_entry}
@@ -436,9 +450,21 @@ commands.deny = ["{command}"]
436450
);
437451

438452
let out_path = path.join(format!("{command}.toml"));
439-
if toml != read_to_string(&out_path).unwrap_or_default() {
440-
std::fs::write(out_path, toml)
441-
.unwrap_or_else(|_| panic!("unable to autogenerate ${command}.toml"));
442-
}
453+
write_if_changed(&toml, &out_path);
454+
455+
autogenerated
456+
.allowed
457+
.push(format!("allow-{slugified_command}"));
458+
autogenerated
459+
.denied
460+
.push(format!("deny-{slugified_command}"));
461+
}
462+
463+
autogenerated
464+
}
465+
466+
fn write_if_changed(content: &str, path: &Path) {
467+
if content != read_to_string(path).unwrap_or_default() {
468+
std::fs::write(path, content).unwrap_or_else(|_| panic!("unable to autogenerate {path:?}"));
443469
}
444470
}

0 commit comments

Comments
 (0)