enhance: include permission group permissions in the generated schema (#13057)

* enhance: include permissions in default permission description

* Only include in schema

* Remove 'which includes` to tauri's build script

* Also bump utils

* Clippy
My local clippy didn't report this, weird

* Use `which enables all commands`
for default permissions that enables everything

* Extract description into a variable

* Generate permissions with or without description

* Tweak the docs and generate 'which includes'

* Simplify to just `includes`

* Docs change change file

* Put the change in minor

* Update .changes/include-permissions-in-schema.md

Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com>

* Remove unused change file

---------

Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com>
This commit is contained in:
Tony 2025-03-23 21:35:45 +08:00 committed by GitHub
parent be31675fbc
commit a851b6597f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 112 additions and 29 deletions

View File

@ -0,0 +1,6 @@
---
tauri: minor:enhance
tauri-utils: minor:enhance
---
Enhanced the description of generated docs and schema for permission sets to include list of permissions within.

View File

@ -356,9 +356,10 @@ pub fn generate_docs(
default_permission.push_str(default.description.as_deref().unwrap_or_default());
default_permission.push('\n');
default_permission.push('\n');
default_permission.push_str("#### This default permission set includes the following:\n");
default_permission.push('\n');
for permission in &default.permissions {
default_permission.push_str(&format!("- `{permission}`"));
default_permission.push('\n');
default_permission.push_str(&format!("- `{permission}`\n"));
}
}

View File

@ -42,6 +42,9 @@ pub trait PermissionSchemaGenerator<
/// Default permission set description if any.
fn default_set_description(&self) -> Option<&str>;
/// Default permission set's permissions if any.
fn default_set_permissions(&self) -> Option<&Vec<String>>;
/// Permissions sets to generate schema for.
fn permission_sets(&'a self) -> Ps;
@ -56,6 +59,18 @@ pub trait PermissionSchemaGenerator<
_ => id.to_string(),
};
let extensions = if let Some(description) = description {
[(
// This is non-standard, and only used by vscode right now,
// but it does work really well
"markdownDescription".to_string(),
serde_json::Value::String(description.to_string()),
)]
.into()
} else {
Default::default()
};
Schema::Object(SchemaObject {
metadata: Some(Box::new(Metadata {
description: description.map(ToString::to_string),
@ -63,6 +78,7 @@ pub trait PermissionSchemaGenerator<
})),
instance_type: Some(InstanceType::String.into()),
const_value: Some(serde_json::Value::String(command_name)),
extensions,
..Default::default()
})
}
@ -73,13 +89,22 @@ pub trait PermissionSchemaGenerator<
// schema for default set
if self.has_default_permission_set() {
let default = Self::perm_id_schema(name, "default", self.default_set_description());
permission_schemas.push(default);
let description = self.default_set_description().unwrap_or_default();
let description = if let Some(permissions) = self.default_set_permissions() {
add_permissions_to_description(description, permissions, true)
} else {
description.to_string()
};
if !description.is_empty() {
let default = Self::perm_id_schema(name, "default", Some(&description));
permission_schemas.push(default);
}
}
// schema for each permission set
for set in self.permission_sets() {
let schema = Self::perm_id_schema(name, &set.identifier, Some(&set.description));
let description = add_permissions_to_description(&set.description, &set.permissions, false);
let schema = Self::perm_id_schema(name, &set.identifier, Some(&description));
permission_schemas.push(schema);
}
@ -93,6 +118,27 @@ pub trait PermissionSchemaGenerator<
}
}
fn add_permissions_to_description(
description: &str,
permissions: &[String],
is_default: bool,
) -> String {
if permissions.is_empty() {
return description.to_string();
}
let permissions_list = permissions
.iter()
.map(|permission| format!("- `{permission}`"))
.collect::<Vec<_>>()
.join("\n");
let default_permission_set = if is_default {
"default permission set"
} else {
"permission set"
};
format!("{description}\n#### This {default_permission_set} includes:\n\n{permissions_list}")
}
impl<'a>
PermissionSchemaGenerator<
'a,
@ -111,6 +157,10 @@ impl<'a>
.map(|d| d.description.as_str())
}
fn default_set_permissions(&self) -> Option<&Vec<String>> {
self.default_permission.as_ref().map(|d| &d.permissions)
}
fn permission_sets(&'a self) -> Values<'a, std::string::String, PermissionSet> {
self.permission_sets.values()
}
@ -131,6 +181,10 @@ impl<'a> PermissionSchemaGenerator<'a, Iter<'a, PermissionSet>, Iter<'a, Permiss
self.default.as_ref().and_then(|d| d.description.as_deref())
}
fn default_set_permissions(&self) -> Option<&Vec<String>> {
self.default.as_ref().map(|d| &d.permissions)
}
fn permission_sets(&'a self) -> Iter<'a, PermissionSet> {
self.set.iter()
}

View File

@ -373,9 +373,10 @@ fn define_permissions(
LICENSE_HEADER,
false,
);
let default_permissions = commands
.iter()
.filter(|(_cmd, default)| *default)
let default_permissions: Vec<_> = commands.iter().filter(|(_cmd, default)| *default).collect();
let all_commands_enabled_by_default = commands.len() == default_permissions.len();
let default_permissions = default_permissions
.into_iter()
.map(|(cmd, _)| {
let slugified_command = cmd.replace('_', "-");
format!("\"allow-{slugified_command}\"")
@ -383,11 +384,17 @@ fn define_permissions(
.collect::<Vec<_>>()
.join(", ");
let all_enable_by_default = if all_commands_enabled_by_default {
", which enables all commands"
} else {
""
};
let default_toml = format!(
r###"{LICENSE_HEADER}# Automatically generated - DO NOT EDIT!
[default]
description = "Default permissions for the plugin."
description = "Default permissions for the plugin{all_enable_by_default}."
permissions = [{default_permissions}]
"###,
);
@ -437,22 +444,15 @@ fn define_default_permission_set(
let default_toml = permissions_out_dir.join("default.toml");
let toml_content = format!(
r#"# {LICENSE_HEADER}
r#"{LICENSE_HEADER}
[default]
description = """Default core plugins set which includes:
{}
"""
description = "Default core plugins set."
permissions = [{}]
"#,
PLUGINS
.iter()
.map(|(k, _)| format!("- '{k}:default'"))
.collect::<Vec<_>>()
.join("\n"),
PLUGINS
.iter()
.map(|(k, _)| format!("'{k}:default'"))
.map(|(k, _)| format!("\"{k}:default\""))
.collect::<Vec<_>>()
.join(",")
);

View File

@ -2,6 +2,8 @@
Default permissions for the plugin.
#### This default permission set includes the following:
- `allow-version`
- `allow-name`
- `allow-tauri-version`

View File

@ -1,6 +1,8 @@
## Default Permission
Default permissions for the plugin.
Default permissions for the plugin, which enables all commands.
#### This default permission set includes the following:
- `allow-listen`
- `allow-unlisten`

View File

@ -1,6 +1,8 @@
## Default Permission
Default permissions for the plugin.
Default permissions for the plugin, which enables all commands.
#### This default permission set includes the following:
- `allow-new`
- `allow-from-bytes`

View File

@ -1,6 +1,8 @@
## Default Permission
Default permissions for the plugin.
Default permissions for the plugin, which enables all commands.
#### This default permission set includes the following:
- `allow-new`
- `allow-append`

View File

@ -1,6 +1,8 @@
## Default Permission
Default permissions for the plugin.
Default permissions for the plugin, which enables all commands.
#### This default permission set includes the following:
- `allow-resolve-directory`
- `allow-resolve`

View File

@ -1,6 +1,8 @@
## Default Permission
Default permissions for the plugin.
Default permissions for the plugin, which enables all commands.
#### This default permission set includes the following:
- `allow-close`

View File

@ -1,6 +1,8 @@
## Default Permission
Default permissions for the plugin.
Default permissions for the plugin, which enables all commands.
#### This default permission set includes the following:
- `allow-new`
- `allow-get-by-id`

View File

@ -2,6 +2,8 @@
Default permissions for the plugin.
#### This default permission set includes the following:
- `allow-get-all-webviews`
- `allow-webview-position`
- `allow-webview-size`

View File

@ -2,6 +2,8 @@
Default permissions for the plugin.
#### This default permission set includes the following:
- `allow-get-all-windows`
- `allow-scale-factor`
- `allow-inner-position`

View File

@ -297,22 +297,26 @@
{
"description": "Enables the ping command without any pre-configured scope.",
"type": "string",
"const": "allow-ping"
"const": "allow-ping",
"markdownDescription": "Enables the ping command without any pre-configured scope."
},
{
"description": "Denies the ping command without any pre-configured scope.",
"type": "string",
"const": "deny-ping"
"const": "deny-ping",
"markdownDescription": "Denies the ping command without any pre-configured scope."
},
{
"description": "Sets a global scope.",
"type": "string",
"const": "global-scope"
"const": "global-scope",
"markdownDescription": "Sets a global scope."
},
{
"description": "Enables the ping command with a test scope.",
"type": "string",
"const": "allow-ping-scoped"
"const": "allow-ping-scoped",
"markdownDescription": "Enables the ping command with a test scope."
}
]
}