use clap::Parser;
use crate::{
error::{Context, ErrorExt},
Result,
};
use colored::Colorize;
use tauri_utils::acl::{manifest::Manifest, APP_ACL_KEY};
use std::{collections::BTreeMap, fs::read_to_string};
#[derive(Debug, Parser)]
#[clap(about = "List permissions available to your application")]
pub struct Options {
plugin: Option<String>,
#[clap(short, long)]
filter: Option<String>,
}
pub fn command(options: Options) -> Result<()> {
let dirs = crate::helpers::app_paths::resolve_dirs();
let acl_manifests_path = dirs
.tauri
.join("gen")
.join("schemas")
.join("acl-manifests.json");
if acl_manifests_path.exists() {
let plugin_manifest_json = read_to_string(&acl_manifests_path)
.fs_context("failed to read plugin manifest", acl_manifests_path)?;
let acl = serde_json::from_str::<BTreeMap<String, Manifest>>(&plugin_manifest_json)
.context("failed to parse plugin manifest as JSON")?;
for (key, manifest) in acl {
if options
.plugin
.as_ref()
.map(|p| p != &key)
.unwrap_or_default()
{
continue;
}
let mut permissions = Vec::new();
let prefix = if key == APP_ACL_KEY {
"".to_string()
} else {
format!("{}:", key.magenta())
};
if let Some(default) = manifest.default_permission {
if options
.filter
.as_ref()
.map(|f| "default".contains(f))
.unwrap_or(true)
{
permissions.push(format!(
"{prefix}{}\n{}\nPermissions: {}",
"default".cyan(),
default.description,
default
.permissions
.iter()
.map(|c| c.cyan().to_string())
.collect::<Vec<_>>()
.join(", ")
));
}
}
for set in manifest.permission_sets.values() {
if options
.filter
.as_ref()
.map(|f| set.identifier.contains(f))
.unwrap_or(true)
{
permissions.push(format!(
"{prefix}{}\n{}\nPermissions: {}",
set.identifier.cyan(),
set.description,
set
.permissions
.iter()
.map(|c| c.cyan().to_string())
.collect::<Vec<_>>()
.join(", ")
));
}
}
for permission in manifest.permissions.into_values() {
if options
.filter
.as_ref()
.map(|f| permission.identifier.contains(f))
.unwrap_or(true)
{
permissions.push(format!(
"{prefix}{}{}{}{}",
permission.identifier.cyan(),
permission
.description
.map(|d| format!("\n{d}"))
.unwrap_or_default(),
if permission.commands.allow.is_empty() {
"".to_string()
} else {
format!(
"\n{}: {}",
"Allow commands".bold(),
permission
.commands
.allow
.iter()
.map(|c| c.green().to_string())
.collect::<Vec<_>>()
.join(", ")
)
},
if permission.commands.deny.is_empty() {
"".to_string()
} else {
format!(
"\n{}: {}",
"Deny commands".bold(),
permission
.commands
.deny
.iter()
.map(|c| c.red().to_string())
.collect::<Vec<_>>()
.join(", ")
)
},
));
}
}
if !permissions.is_empty() {
println!("{}\n", permissions.join("\n\n"));
}
}
Ok(())
} else {
crate::error::bail!("permission file not found, please build your application once first")
}
}