rm.rs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // Copyright 2019-2023 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. use std::path::Path;
  5. use clap::Parser;
  6. use tauri_utils::acl::{plugin::PermissionFile, PERMISSION_SCHEMA_FILE_NAME};
  7. use crate::{acl::FileFormat, helpers::app_paths::tauri_dir_opt, Result};
  8. fn rm_permission_files(identifier: &str, dir: &Path) -> Result<()> {
  9. for entry in std::fs::read_dir(dir)?.flatten() {
  10. let file_type = entry.file_type()?;
  11. let path = entry.path();
  12. if file_type.is_dir() {
  13. rm_permission_files(identifier, &path)?;
  14. } else {
  15. if path
  16. .file_name()
  17. .map(|name| name == PERMISSION_SCHEMA_FILE_NAME)
  18. .unwrap_or_default()
  19. {
  20. continue;
  21. }
  22. let (mut permission_file, format): (PermissionFile, FileFormat) =
  23. match path.extension().and_then(|o| o.to_str()) {
  24. Some("toml") => {
  25. let content = std::fs::read_to_string(&path)?;
  26. (toml::from_str(&content)?, FileFormat::Toml)
  27. }
  28. Some("json") => {
  29. let content = std::fs::read(&path)?;
  30. (serde_json::from_slice(&content)?, FileFormat::Json)
  31. }
  32. _ => {
  33. continue;
  34. }
  35. };
  36. let mut updated;
  37. if identifier == "default" {
  38. updated = permission_file.default.is_some();
  39. permission_file.default = None;
  40. } else {
  41. let set_len = permission_file.set.len();
  42. permission_file.set.retain(|s| s.identifier != identifier);
  43. updated = permission_file.set.len() != set_len;
  44. let permission_len = permission_file.permission.len();
  45. permission_file
  46. .permission
  47. .retain(|s| s.identifier != identifier);
  48. updated = updated || permission_file.permission.len() != permission_len;
  49. }
  50. // if the file is empty, let's remove it
  51. if permission_file.default.is_none()
  52. && permission_file.set.is_empty()
  53. && permission_file.permission.is_empty()
  54. {
  55. std::fs::remove_file(&path)?;
  56. log::info!(action = "Removed"; "file {}", dunce::simplified(&path).display());
  57. } else if updated {
  58. std::fs::write(&path, format.serialize(&permission_file)?)?;
  59. log::info!(action = "Removed"; "permission {identifier} from {}", dunce::simplified(&path).display());
  60. }
  61. }
  62. }
  63. Ok(())
  64. }
  65. fn rm_permission_from_capabilities(identifier: &str, dir: &Path) -> Result<()> {
  66. for entry in std::fs::read_dir(dir)?.flatten() {
  67. let file_type = entry.file_type()?;
  68. if file_type.is_file() {
  69. let path = entry.path();
  70. match path.extension().and_then(|o| o.to_str()) {
  71. Some("toml") => {
  72. let content = std::fs::read_to_string(&path)?;
  73. if let Ok(mut value) = content.parse::<toml_edit::Document>() {
  74. if let Some(permissions) = value.get_mut("permissions").and_then(|p| p.as_array_mut()) {
  75. let prev_len = permissions.len();
  76. permissions.retain(|p| p.as_str().map(|p| p != identifier).unwrap_or(false));
  77. if prev_len != permissions.len() {
  78. std::fs::write(&path, value.to_string())?;
  79. log::info!(action = "Removed"; "permission from capability at {}", dunce::simplified(&path).display());
  80. }
  81. }
  82. }
  83. }
  84. Some("json") => {
  85. let content = std::fs::read(&path)?;
  86. if let Ok(mut value) = serde_json::from_slice::<serde_json::Value>(&content) {
  87. if let Some(permissions) = value.get_mut("permissions").and_then(|p| p.as_array_mut()) {
  88. let prev_len = permissions.len();
  89. permissions.retain(|p| p.as_str().map(|p| p != identifier).unwrap_or(false));
  90. if prev_len != permissions.len() {
  91. std::fs::write(&path, serde_json::to_vec_pretty(&value)?)?;
  92. log::info!(action = "Removed"; "permission from capability at {}", dunce::simplified(&path).display());
  93. }
  94. }
  95. }
  96. }
  97. _ => {}
  98. }
  99. }
  100. }
  101. Ok(())
  102. }
  103. #[derive(Debug, Parser)]
  104. #[clap(about = "Remove a permission file, and its reference from any capability")]
  105. pub struct Options {
  106. /// Permission to remove.
  107. identifier: String,
  108. }
  109. pub fn command(options: Options) -> Result<()> {
  110. let permissions_dir = std::env::current_dir()?.join("permissions");
  111. if permissions_dir.exists() {
  112. rm_permission_files(&options.identifier, &permissions_dir)?;
  113. }
  114. if let Some(tauri_dir) = tauri_dir_opt() {
  115. let capabilities_dir = tauri_dir.join("capabilities");
  116. if capabilities_dir.exists() {
  117. rm_permission_from_capabilities(&options.identifier, &capabilities_dir)?;
  118. }
  119. }
  120. Ok(())
  121. }