From 1e05d566b61a4f5d91e086b84fd3e20f50d39432 Mon Sep 17 00:00:00 2001 From: Jae-Heon Ji Date: Wed, 26 Jul 2023 03:16:39 +0900 Subject: [PATCH] fix: don't save permission data in memory --- zellij-server/src/panes/plugin_pane.rs | 12 +++-- zellij-server/src/plugins/mod.rs | 35 ++++++------- zellij-server/src/plugins/plugin_loader.rs | 35 ++----------- zellij-server/src/plugins/plugin_map.rs | 9 ++-- zellij-server/src/plugins/wasm_bridge.rs | 55 ++++++++++----------- zellij-server/src/plugins/zellij_exports.rs | 11 +---- zellij-server/src/screen.rs | 13 +++++ zellij-server/src/tab/mod.rs | 10 ++-- zellij-utils/src/data.rs | 8 ++- zellij-utils/src/input/permission.rs | 20 +++++++- 10 files changed, 104 insertions(+), 104 deletions(-) diff --git a/zellij-server/src/panes/plugin_pane.rs b/zellij-server/src/panes/plugin_pane.rs index 2075484ac..9ffc8df3d 100644 --- a/zellij-server/src/panes/plugin_pane.rs +++ b/zellij-server/src/panes/plugin_pane.rs @@ -13,7 +13,7 @@ use crate::ui::{ use crate::ClientId; use std::cell::RefCell; use std::rc::Rc; -use zellij_utils::data::{PermissionType, PluginPermission}; +use zellij_utils::data::{PermissionStatus, PermissionType, PluginPermission}; use zellij_utils::pane_size::{Offset, SizeInPixels}; use zellij_utils::position::Position; use zellij_utils::{ @@ -228,9 +228,15 @@ impl Pane for PluginPane { let permissions = requesting_permissions.permissions.clone(); match input_bytes.as_slice() { // Y or y - &[89] | &[121] => Some(AdjustedInput::PermissionRequestResult(permissions, true)), + &[89] | &[121] => Some(AdjustedInput::PermissionRequestResult( + permissions, + PermissionStatus::Granted, + )), // N or n - &[78] | &[110] => Some(AdjustedInput::PermissionRequestResult(permissions, false)), + &[78] | &[110] => Some(AdjustedInput::PermissionRequestResult( + permissions, + PermissionStatus::Denied, + )), _ => None, } } else { diff --git a/zellij-server/src/plugins/mod.rs b/zellij-server/src/plugins/mod.rs index 50486b9a7..40f49e890 100644 --- a/zellij-server/src/plugins/mod.rs +++ b/zellij-server/src/plugins/mod.rs @@ -18,13 +18,11 @@ use crate::{pty::PtyInstruction, thread_bus::Bus, ClientId, ServerInstruction}; use wasm_bridge::WasmBridge; use zellij_utils::{ - consts::ZELLIJ_PLUGIN_PERMISSIONS_FILE, - data::{Event, EventType, PermissionType, PluginCapabilities}, + data::{Event, EventType, PermissionStatus, PermissionType, PluginCapabilities}, errors::{prelude::*, ContextType, PluginContext}, input::{ command::TerminalAction, layout::{FloatingPaneLayout, Layout, Run, RunPlugin, RunPluginLocation, TiledPaneLayout}, - permission::GrantedPermission, plugins::PluginsConfig, }, ipc::ClientAttributes, @@ -81,7 +79,12 @@ pub enum PluginInstruction { String, // serialized payload ), PluginSubscribedToEvents(PluginId, ClientId, HashSet), - PermissionRequestResult(PluginId, Option, Vec, bool), + PermissionRequestResult( + PluginId, + Option, + Vec, + PermissionStatus, + ), Exit, } @@ -132,21 +135,11 @@ pub(crate) fn plugin_thread_main( let plugin_dir = data_dir.join("plugins/"); let plugin_global_data_dir = plugin_dir.join("data"); - let granted_permission = - match fs::read_to_string(plugin_dir.join(ZELLIJ_PLUGIN_PERMISSIONS_FILE)) { - Ok(s) => match GrantedPermission::from_string(s) { - Ok(p) => p, - Err(_) => GrantedPermission::default(), - }, - Err(_) => GrantedPermission::default(), - }; - let mut wasm_bridge = WasmBridge::new( plugins, bus.senders.clone(), store, plugin_dir, - granted_permission, path_to_default_shell, zellij_cwd, capabilities, @@ -305,11 +298,15 @@ pub(crate) fn plugin_thread_main( PluginInstruction::PermissionRequestResult( plugin_id, client_id, - permissions, - result, + plugin_permission, + status, ) => { - let permissions = if result { permissions } else { Vec::new() }; - match wasm_bridge.caching_plugin_permissions(plugin_id, client_id, permissions) { + match wasm_bridge.caching_plugin_permissions( + plugin_id, + client_id, + plugin_permission, + status, + ) { Ok(_) => {}, Err(e) => log::error!("{}", e), } @@ -317,7 +314,7 @@ pub(crate) fn plugin_thread_main( let updates = vec![( Some(plugin_id), client_id, - Event::PermissionRequestResult(result), + Event::PermissionRequestResult(status), )]; wasm_bridge.update_plugins(updates)?; }, diff --git a/zellij-server/src/plugins/plugin_loader.rs b/zellij-server/src/plugins/plugin_loader.rs index 1ad833304..79ab0e714 100644 --- a/zellij-server/src/plugins/plugin_loader.rs +++ b/zellij-server/src/plugins/plugin_loader.rs @@ -14,8 +14,6 @@ use std::{ use url::Url; use wasmer::{ChainableNamedResolver, Instance, Module, Store}; use wasmer_wasi::{Pipe, WasiState}; -use zellij_utils::data::PermissionType; -use zellij_utils::input::permission::GrantedPermission; use crate::{ logging_pipe::LoggingPipe, screen::ScreenInstruction, thread_bus::ThreadSenders, @@ -165,7 +163,6 @@ pub struct PluginLoader<'a> { store: Store, plugin: PluginConfig, plugin_dir: &'a PathBuf, - plugin_permissions: Option>, tab_index: usize, plugin_own_data_dir: PathBuf, size: Size, @@ -183,7 +180,6 @@ impl<'a> PluginLoader<'a> { plugin_id: PluginId, plugin_dir: PathBuf, plugin_cache: Arc>>, - plugin_permissions: Option>, senders: ThreadSenders, store: Store, plugin_map: Arc>, @@ -213,7 +209,6 @@ impl<'a> PluginLoader<'a> { first_client_id, &store, &plugin_dir, - plugin_permissions, path_to_default_shell, zellij_cwd, capabilities, @@ -247,7 +242,6 @@ impl<'a> PluginLoader<'a> { tab_index: usize, plugin_dir: PathBuf, plugin_cache: Arc>>, - plugin_permissions: Option>, senders: ThreadSenders, store: Store, plugin_map: Arc>, @@ -271,7 +265,6 @@ impl<'a> PluginLoader<'a> { &store, plugin.clone(), &plugin_dir, - plugin_permissions, tab_index, size, path_to_default_shell, @@ -309,7 +302,6 @@ impl<'a> PluginLoader<'a> { client_id: ClientId, plugin_dir: PathBuf, plugin_cache: Arc>>, - granted_permission: &GrantedPermission, senders: ThreadSenders, store: Store, plugin_map: Arc>, @@ -323,14 +315,10 @@ impl<'a> PluginLoader<'a> { default_layout: Box, ) -> Result<()> { let mut new_plugins = HashSet::new(); - for (plugin_id, _, running_plugin) in plugin_map.lock().unwrap().running_plugins() { - let running_plugin = running_plugin.lock().unwrap(); - let plugin_permissions = - granted_permission.get(&running_plugin.plugin_env.plugin.location.to_string()); - - new_plugins.insert((plugin_id, client_id, plugin_permissions.cloned())); + for plugin_id in plugin_map.lock().unwrap().plugin_ids() { + new_plugins.insert((plugin_id, client_id)); } - for (plugin_id, existing_client_id, plugin_permissions) in new_plugins { + for (plugin_id, existing_client_id) in new_plugins { let mut plugin_loader = PluginLoader::new_from_different_client_id( &plugin_cache, &plugin_map, @@ -340,7 +328,6 @@ impl<'a> PluginLoader<'a> { existing_client_id, &store, &plugin_dir, - plugin_permissions, path_to_default_shell.clone(), zellij_cwd.clone(), capabilities.clone(), @@ -368,7 +355,6 @@ impl<'a> PluginLoader<'a> { plugin_id: PluginId, plugin_dir: PathBuf, plugin_cache: Arc>>, - plugin_permissions: Option>, senders: ThreadSenders, store: Store, plugin_map: Arc>, @@ -399,7 +385,6 @@ impl<'a> PluginLoader<'a> { first_client_id, &store, &plugin_dir, - plugin_permissions, path_to_default_shell, zellij_cwd, capabilities, @@ -434,7 +419,6 @@ impl<'a> PluginLoader<'a> { store: &Store, plugin: PluginConfig, plugin_dir: &'a PathBuf, - plugin_permissions: Option>, tab_index: usize, size: Size, path_to_default_shell: PathBuf, @@ -459,7 +443,6 @@ impl<'a> PluginLoader<'a> { store: store.clone(), plugin, plugin_dir, - plugin_permissions, tab_index, plugin_own_data_dir, size, @@ -481,7 +464,6 @@ impl<'a> PluginLoader<'a> { client_id: ClientId, store: &Store, plugin_dir: &'a PathBuf, - plugin_permissions: Option>, path_to_default_shell: PathBuf, zellij_cwd: PathBuf, capabilities: PluginCapabilities, @@ -513,7 +495,6 @@ impl<'a> PluginLoader<'a> { store, plugin_config, plugin_dir, - plugin_permissions, tab_index, size, path_to_default_shell, @@ -533,7 +514,6 @@ impl<'a> PluginLoader<'a> { client_id: ClientId, store: &Store, plugin_dir: &'a PathBuf, - plugin_permissions: Option>, path_to_default_shell: PathBuf, zellij_cwd: PathBuf, capabilities: PluginCapabilities, @@ -566,7 +546,6 @@ impl<'a> PluginLoader<'a> { store, plugin_config, plugin_dir, - plugin_permissions, tab_index, size, path_to_default_shell, @@ -812,7 +791,6 @@ impl<'a> PluginLoader<'a> { *client_id, &self.store, &self.plugin_dir, - self.plugin_permissions.clone(), self.path_to_default_shell.clone(), self.zellij_cwd.clone(), self.capabilities.clone(), @@ -890,18 +868,13 @@ impl<'a> PluginLoader<'a> { }) .with_context(err_context)?; let wasi = wasi_env.import_object(&module).with_context(err_context)?; - let plugin_permissions = match &self.plugin_permissions { - Some(p) => Some(HashSet::from_iter(p.clone())), - None => None, - }; - let mut mut_plugin = self.plugin.clone(); mut_plugin.set_tab_index(self.tab_index); let plugin_env = PluginEnv { plugin_id: self.plugin_id, client_id: self.client_id, plugin: mut_plugin, - plugin_permissions, + permissions: HashSet::default(), senders: self.senders.clone(), wasi_env, plugin_own_data_dir: self.plugin_own_data_dir.clone(), diff --git a/zellij-server/src/plugins/plugin_map.rs b/zellij-server/src/plugins/plugin_map.rs index 26d8d41c0..3f1453265 100644 --- a/zellij-server/src/plugins/plugin_map.rs +++ b/zellij-server/src/plugins/plugin_map.rs @@ -193,7 +193,7 @@ pub type Subscriptions = HashSet; pub struct PluginEnv { pub plugin_id: PluginId, pub plugin: PluginConfig, - pub plugin_permissions: Option>, + pub permissions: HashSet, pub senders: ThreadSenders, pub wasi_env: WasiEnv, pub tab_index: usize, @@ -217,11 +217,8 @@ impl PluginEnv { ) } - pub fn merge_plugin_permissions(&mut self, permissions: HashSet) { - match &mut self.plugin_permissions { - Some(p) => p.extend(permissions), - None => self.plugin_permissions = Some(permissions), - } + pub fn merge_permissions(&mut self, permissions: HashSet) { + self.permissions.extend(permissions); } } diff --git a/zellij-server/src/plugins/wasm_bridge.rs b/zellij-server/src/plugins/wasm_bridge.rs index 2bce89ef2..cb3b44886 100644 --- a/zellij-server/src/plugins/wasm_bridge.rs +++ b/zellij-server/src/plugins/wasm_bridge.rs @@ -15,8 +15,8 @@ use std::{ }; use wasmer::{Instance, Module, Store, Value}; use zellij_utils::async_std::task::{self, JoinHandle}; -use zellij_utils::consts::ZELLIJ_PLUGIN_PERMISSIONS_FILE; -use zellij_utils::data::PermissionType; +use zellij_utils::consts::{ZELLIJ_CACHE_DIR, ZELLIJ_PLUGIN_PERMISSIONS_FILE}; +use zellij_utils::data::{PermissionStatus, PermissionType, PluginPermission}; use zellij_utils::input::permission::GrantedPermission; use zellij_utils::notify_debouncer_full::{notify::RecommendedWatcher, Debouncer, FileIdMap}; @@ -50,7 +50,6 @@ pub struct WasmBridge { plugin_dir: PathBuf, plugin_cache: Arc>>, plugin_map: Arc>, - granted_permission: GrantedPermission, next_plugin_id: PluginId, cached_events_for_pending_plugins: HashMap>, cached_resizes_for_pending_plugins: HashMap, // (rows, columns) @@ -75,7 +74,6 @@ impl WasmBridge { senders: ThreadSenders, store: Store, plugin_dir: PathBuf, - granted_permission: GrantedPermission, path_to_default_shell: PathBuf, zellij_cwd: PathBuf, capabilities: PluginCapabilities, @@ -96,7 +94,6 @@ impl WasmBridge { plugin_dir, plugin_cache, plugin_map, - granted_permission, path_to_default_shell, watcher, next_plugin_id: 0, @@ -152,10 +149,6 @@ impl WasmBridge { let load_plugin_task = task::spawn({ let plugin_dir = self.plugin_dir.clone(); let plugin_cache = self.plugin_cache.clone(); - let plugin_permissions = self - .granted_permission - .get(&run.location.to_string()) - .cloned(); let senders = self.senders.clone(); let store = self.store.clone(); let plugin_map = self.plugin_map.clone(); @@ -177,7 +170,6 @@ impl WasmBridge { tab_index, plugin_dir, plugin_cache, - plugin_permissions, senders.clone(), store, plugin_map, @@ -245,10 +237,6 @@ impl WasmBridge { let load_plugin_task = task::spawn({ let plugin_dir = self.plugin_dir.clone(); let plugin_cache = self.plugin_cache.clone(); - let plugin_permissions = self - .granted_permission - .get(&run_plugin.location.to_string()) - .cloned(); let senders = self.senders.clone(); let store = self.store.clone(); let plugin_map = self.plugin_map.clone(); @@ -264,7 +252,6 @@ impl WasmBridge { first_plugin_id, plugin_dir.clone(), plugin_cache.clone(), - plugin_permissions.clone(), senders.clone(), store.clone(), plugin_map.clone(), @@ -289,7 +276,6 @@ impl WasmBridge { *plugin_id, plugin_dir.clone(), plugin_cache.clone(), - plugin_permissions.clone(), senders.clone(), store.clone(), plugin_map.clone(), @@ -336,7 +322,6 @@ impl WasmBridge { client_id, self.plugin_dir.clone(), self.plugin_cache.clone(), - &self.granted_permission, self.senders.clone(), self.store.clone(), self.plugin_map.clone(), @@ -734,6 +719,7 @@ impl WasmBridge { plugin_id: PluginId, client_id: Option, permissions: Vec, + status: PermissionStatus, ) -> Result<()> { if let Some(running_plugin) = self .plugin_map @@ -744,18 +730,33 @@ impl WasmBridge { let err_context = || format!("Failed to write plugin permission {plugin_id}"); let mut running_plugin = running_plugin.lock().unwrap(); - running_plugin - .plugin_env - .merge_plugin_permissions(HashSet::from_iter(permissions.clone())); - self.granted_permission.insert( + let permissions = HashSet::from_iter(permissions); + match status { + PermissionStatus::Granted => { + running_plugin.plugin_env.merge_permissions(permissions) + }, + PermissionStatus::Denied => { + permissions.iter().for_each(|p| { + running_plugin.plugin_env.permissions.remove(p); + }); + }, + } + + let mut granted_permission = GrantedPermission::from_default().unwrap_or_default(); + granted_permission.insert( running_plugin.plugin_env.plugin.location.to_string(), - permissions, + running_plugin + .plugin_env + .permissions + .clone() + .into_iter() + .collect(), ); - let mut f = File::create(self.plugin_dir.join(ZELLIJ_PLUGIN_PERMISSIONS_FILE)) + let mut f = File::create(ZELLIJ_CACHE_DIR.join(ZELLIJ_PLUGIN_PERMISSIONS_FILE)) .with_context(err_context)?; - write!(f, "{}", self.granted_permission.to_string()).with_context(err_context)?; + write!(f, "{}", granted_permission.to_string()).with_context(err_context)?; } Ok(()) @@ -788,10 +789,8 @@ fn check_permission(plugin_env: &PluginEnv, event: &Event) -> Permission { _ => return Permission::Allowed, }; - if let Some(permissions) = &plugin_env.plugin_permissions { - if !permissions.contains(&permission) { - return Permission::Denied(permission); - } + if !plugin_env.permissions.contains(&permission) { + return Permission::Denied(permission); } Permission::Allowed diff --git a/zellij-server/src/plugins/zellij_exports.rs b/zellij-server/src/plugins/zellij_exports.rs index ddc7906f6..21d0b863f 100644 --- a/zellij-server/src/plugins/zellij_exports.rs +++ b/zellij-server/src/plugins/zellij_exports.rs @@ -217,20 +217,11 @@ fn host_set_selectable(env: &ForeignFunctionEnv, selectable: i32) { fn host_request_permission(env: &ForeignFunctionEnv) { wasi_read_object::>(&env.plugin_env.wasi_env) .and_then(|permissions| { - if let Some(permissions) = &env.plugin_env.plugin_permissions { - if !permissions.is_empty() { - return Ok(()); - } - } - env.plugin_env .senders .send_to_screen(ScreenInstruction::RequestPluginPermissions( env.plugin_env.plugin_id, - PluginPermission::new( - env.plugin_env.plugin.path.display().to_string(), - permissions, - ), + PluginPermission::new(env.plugin_env.plugin.location.to_string(), permissions), )) }) .with_context(|| { diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs index 6dd597aad..d0eab9a3f 100644 --- a/zellij-server/src/screen.rs +++ b/zellij-server/src/screen.rs @@ -10,6 +10,7 @@ use zellij_utils::data::{Direction, PaneManifest, PluginPermission, Resize, Resi use zellij_utils::errors::prelude::*; use zellij_utils::input::command::RunCommand; use zellij_utils::input::options::Clipboard; +use zellij_utils::input::permission::GrantedPermission; use zellij_utils::pane_size::{Size, SizeInPixels}; use zellij_utils::{ input::command::TerminalAction, @@ -2823,6 +2824,18 @@ pub(crate) fn screen_thread_main( screen.report_tab_state()?; }, ScreenInstruction::RequestPluginPermissions(plugin_id, permissions) => { + let permissions = match GrantedPermission::from_default() { + Ok(granted_permission) => { + if let Some(p) = granted_permission.get(&permissions.name) { + // TODO: How to deal cached data? + permissions + } else { + permissions + } + }, + Err(_) => permissions, + }; + let all_tabs = screen.get_tabs_mut(); let found = all_tabs.values_mut().any(|tab| { if tab.has_plugin(plugin_id) { diff --git a/zellij-server/src/tab/mod.rs b/zellij-server/src/tab/mod.rs index 8e1f54824..a79bb6873 100644 --- a/zellij-server/src/tab/mod.rs +++ b/zellij-server/src/tab/mod.rs @@ -9,7 +9,9 @@ mod swap_layouts; use copy_command::CopyCommand; use std::env::temp_dir; use uuid::Uuid; -use zellij_utils::data::{Direction, PaneInfo, PermissionType, PluginPermission, ResizeStrategy}; +use zellij_utils::data::{ + Direction, PaneInfo, PermissionStatus, PermissionType, PluginPermission, ResizeStrategy, +}; use zellij_utils::errors::prelude::*; use zellij_utils::input::command::RunCommand; use zellij_utils::position::{Column, Line}; @@ -474,7 +476,7 @@ pub trait Pane { pub enum AdjustedInput { WriteBytesToTerminal(Vec), ReRunCommandInThisPane(RunCommand), - PermissionRequestResult(Vec, bool), + PermissionRequestResult(Vec, PermissionStatus), CloseThisPane, } pub fn get_next_terminal_position( @@ -1576,14 +1578,14 @@ impl Tab { .send_to_plugin(PluginInstruction::Update(plugin_updates)) .with_context(err_context)?; }, - Some(AdjustedInput::PermissionRequestResult(permissions, result)) => { + Some(AdjustedInput::PermissionRequestResult(permissions, status)) => { self.request_plugin_permissions(pid, None); self.senders .send_to_plugin(PluginInstruction::PermissionRequestResult( pid, client_id, permissions, - result, + status, )) .with_context(err_context)?; should_update_ui = true; diff --git a/zellij-utils/src/data.rs b/zellij-utils/src/data.rs index 6fa8d8317..55f5a1ec9 100644 --- a/zellij-utils/src/data.rs +++ b/zellij-utils/src/data.rs @@ -494,7 +494,7 @@ pub enum Event { /// A file was deleted somewhere in the Zellij CWD folder FileSystemDelete(Vec), /// A Result of plugin permission request - PermissionRequestResult(bool), + PermissionRequestResult(PermissionStatus), } #[derive(Debug, Clone, PartialEq, EnumDiscriminants, ToString, Serialize, Deserialize)] @@ -840,3 +840,9 @@ pub enum CopyDestination { Primary, System, } + +#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] +pub enum PermissionStatus { + Granted, + Denied, +} diff --git a/zellij-utils/src/input/permission.rs b/zellij-utils/src/input/permission.rs index e8d673afc..81301b0eb 100644 --- a/zellij-utils/src/input/permission.rs +++ b/zellij-utils/src/input/permission.rs @@ -1,6 +1,13 @@ -use std::collections::{hash_map::Iter, HashMap}; +use std::{ + collections::{hash_map::Iter, HashMap}, + fs, +}; -use crate::data::PermissionType; +use crate::{ + consts::{ZELLIJ_CACHE_DIR, ZELLIJ_PLUGIN_PERMISSIONS_FILE}, + data::PermissionType, + input::config::ConfigError, +}; #[derive(Default, Debug)] pub struct GrantedPermission(HashMap>); @@ -17,4 +24,13 @@ impl GrantedPermission { pub fn iter(&self) -> Iter> { self.0.iter() } + + pub fn from_default() -> Result { + let default_permission = ZELLIJ_CACHE_DIR.join(ZELLIJ_PLUGIN_PERMISSIONS_FILE); + + let raw_string = fs::read_to_string(&default_permission) + .map_err(|e| ConfigError::IoPath(e, default_permission.into()))?; + + GrantedPermission::from_string(raw_string) + } }