mirror of
https://github.com/project-gauntlet/gauntlet.git
synced 2025-12-23 10:35:53 +00:00
Add permissions for clipboard
This commit is contained in:
parent
a6e056c060
commit
1fe349db47
7 changed files with 172 additions and 18 deletions
|
|
@ -147,4 +147,5 @@ os = 'windows'
|
|||
[permissions]
|
||||
environment = ["RUST_LOG"]
|
||||
system = ["systemMemoryInfo"]
|
||||
network = ["upload.wikimedia.org", "api.github.com"]
|
||||
network = ["upload.wikimedia.org", "api.github.com"]
|
||||
clipboard = ["read", "write", "clear"]
|
||||
|
|
@ -114,14 +114,34 @@ pub enum DbPluginType {
|
|||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct DbPluginPermissions {
|
||||
#[serde(default)]
|
||||
pub environment: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub high_resolution_time: bool,
|
||||
#[serde(default)]
|
||||
pub network: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub ffi: Vec<PathBuf>,
|
||||
#[serde(default)]
|
||||
pub fs_read_access: Vec<PathBuf>,
|
||||
#[serde(default)]
|
||||
pub fs_write_access: Vec<PathBuf>,
|
||||
#[serde(default)]
|
||||
pub run_subprocess: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub system: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub clipboard: Vec<DbPluginClipboardPermissions>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub enum DbPluginClipboardPermissions {
|
||||
#[serde(rename = "read")]
|
||||
Read,
|
||||
#[serde(rename = "write")]
|
||||
Write,
|
||||
#[serde(rename = "clear")]
|
||||
Clear
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
use std::cell::RefCell;
|
||||
use std::io::Cursor;
|
||||
|
||||
use std::rc::Rc;
|
||||
use anyhow::anyhow;
|
||||
use arboard::ImageData;
|
||||
use deno_core::op;
|
||||
use deno_core::{op, OpState};
|
||||
use image::RgbaImage;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokio::task::spawn_blocking;
|
||||
use crate::plugins::js::{PluginClipboardPermissions, PluginData};
|
||||
|
||||
fn unknown_err_clipboard(err: arboard::Error) -> anyhow::Error {
|
||||
anyhow!("UNKNOWN_ERROR: {:?}", err)
|
||||
|
|
@ -26,7 +28,21 @@ struct ClipboardData {
|
|||
}
|
||||
|
||||
#[op]
|
||||
async fn clipboard_read() -> anyhow::Result<ClipboardData> {
|
||||
async fn clipboard_read(state: Rc<RefCell<OpState>>) -> anyhow::Result<ClipboardData> {
|
||||
{
|
||||
let state = state.borrow();
|
||||
|
||||
let allow = state
|
||||
.borrow::<PluginData>()
|
||||
.permissions()
|
||||
.clipboard
|
||||
.contains(&PluginClipboardPermissions::Read);
|
||||
|
||||
if !allow {
|
||||
return Err(anyhow!("Plugin doesn't have 'read' permission for clipboard"));
|
||||
}
|
||||
}
|
||||
|
||||
spawn_blocking(|| {
|
||||
let mut clipboard = arboard::Clipboard::new()
|
||||
.map_err(|err| unknown_err_clipboard(err))?;
|
||||
|
|
@ -74,7 +90,21 @@ async fn clipboard_read() -> anyhow::Result<ClipboardData> {
|
|||
|
||||
|
||||
#[op]
|
||||
async fn clipboard_read_text() -> anyhow::Result<Option<String>> {
|
||||
async fn clipboard_read_text(state: Rc<RefCell<OpState>>) -> anyhow::Result<Option<String>> {
|
||||
{
|
||||
let state = state.borrow();
|
||||
|
||||
let allow = state
|
||||
.borrow::<PluginData>()
|
||||
.permissions()
|
||||
.clipboard
|
||||
.contains(&PluginClipboardPermissions::Read);
|
||||
|
||||
if !allow {
|
||||
return Err(anyhow!("Plugin doesn't have 'read' permission for clipboard"));
|
||||
}
|
||||
}
|
||||
|
||||
spawn_blocking(|| {
|
||||
let mut clipboard = arboard::Clipboard::new()
|
||||
.map_err(|err| unknown_err_clipboard(err))?;
|
||||
|
|
@ -96,7 +126,21 @@ async fn clipboard_read_text() -> anyhow::Result<Option<String>> {
|
|||
}
|
||||
|
||||
#[op]
|
||||
async fn clipboard_write(data: ClipboardData) -> anyhow::Result<()> { // TODO deserialization broken, fix when migrating to deno's op2
|
||||
async fn clipboard_write(state: Rc<RefCell<OpState>>, data: ClipboardData) -> anyhow::Result<()> { // TODO deserialization broken, fix when migrating to deno's op2
|
||||
{
|
||||
let state = state.borrow();
|
||||
|
||||
let allow = state
|
||||
.borrow::<PluginData>()
|
||||
.permissions()
|
||||
.clipboard
|
||||
.contains(&PluginClipboardPermissions::Write);
|
||||
|
||||
if !allow {
|
||||
return Err(anyhow!("Plugin doesn't have 'write' permission for clipboard"));
|
||||
}
|
||||
}
|
||||
|
||||
spawn_blocking(|| {
|
||||
let mut clipboard = arboard::Clipboard::new()
|
||||
.map_err(|err| unknown_err_clipboard(err))?;
|
||||
|
|
@ -134,7 +178,21 @@ async fn clipboard_write(data: ClipboardData) -> anyhow::Result<()> { // TODO de
|
|||
}
|
||||
|
||||
#[op]
|
||||
async fn clipboard_write_text(data: String) -> anyhow::Result<()> {
|
||||
async fn clipboard_write_text(state: Rc<RefCell<OpState>>, data: String) -> anyhow::Result<()> {
|
||||
{
|
||||
let state = state.borrow();
|
||||
|
||||
let allow = state
|
||||
.borrow::<PluginData>()
|
||||
.permissions()
|
||||
.clipboard
|
||||
.contains(&PluginClipboardPermissions::Write);
|
||||
|
||||
if !allow {
|
||||
return Err(anyhow!("Plugin doesn't have 'write' permission for clipboard"));
|
||||
}
|
||||
}
|
||||
|
||||
spawn_blocking(|| {
|
||||
let mut clipboard = arboard::Clipboard::new()
|
||||
.map_err(|err| unknown_err_clipboard(err))?;
|
||||
|
|
@ -147,7 +205,21 @@ async fn clipboard_write_text(data: String) -> anyhow::Result<()> {
|
|||
}
|
||||
|
||||
#[op]
|
||||
async fn clipboard_clear() -> anyhow::Result<()> {
|
||||
async fn clipboard_clear(state: Rc<RefCell<OpState>>) -> anyhow::Result<()> {
|
||||
{
|
||||
let state = state.borrow();
|
||||
|
||||
let allow = state
|
||||
.borrow::<PluginData>()
|
||||
.permissions()
|
||||
.clipboard
|
||||
.contains(&PluginClipboardPermissions::Clear);
|
||||
|
||||
if !allow {
|
||||
return Err(anyhow!("Plugin doesn't have 'clear' permission for clipboard"));
|
||||
}
|
||||
}
|
||||
|
||||
spawn_blocking(|| {
|
||||
let mut clipboard = arboard::Clipboard::new()
|
||||
.map_err(|err| unknown_err_clipboard(err))?;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ use component_model::{Children, Component, create_component_model, Property, Pro
|
|||
|
||||
use crate::model::{IntermediateUiEvent, JsUiEvent, JsUiPropertyValue, JsUiRenderLocation, JsUiRequestData, JsUiResponseData, JsUiWidget, PreferenceUserData};
|
||||
use crate::plugins::applications::{DesktopEntry, get_apps};
|
||||
use crate::plugins::data_db_repository::{DataDbRepository, db_entrypoint_from_str, DbPluginEntrypointType, DbPluginPreference, DbPluginPreferenceUserData, DbReadPlugin, DbReadPluginEntrypoint};
|
||||
use crate::plugins::data_db_repository::{DataDbRepository, db_entrypoint_from_str, DbPluginEntrypointType, DbPluginPreference, DbPluginPreferenceUserData, DbReadPlugin, DbReadPluginEntrypoint, DbPluginClipboardPermissions};
|
||||
use crate::plugins::icon_cache::IconCache;
|
||||
use crate::plugins::js::assets::{asset_data, asset_data_blocking};
|
||||
use crate::plugins::js::clipboard::{clipboard_clear, clipboard_read, clipboard_read_text, clipboard_write, clipboard_write_text};
|
||||
|
|
@ -82,8 +82,22 @@ pub struct PluginPermissions {
|
|||
pub fs_write_access: Vec<PathBuf>,
|
||||
pub run_subprocess: Vec<String>,
|
||||
pub system: Vec<String>,
|
||||
pub clipboard: Vec<PluginClipboardPermissions>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PluginRuntimePermissions {
|
||||
pub clipboard: Vec<PluginClipboardPermissions>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum PluginClipboardPermissions {
|
||||
Read,
|
||||
Write,
|
||||
Clear
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum PluginCommand {
|
||||
One {
|
||||
|
|
@ -340,6 +354,10 @@ async fn start_js_runtime(
|
|||
None
|
||||
};
|
||||
|
||||
let runtime_permissions = PluginRuntimePermissions {
|
||||
clipboard: permissions.clipboard,
|
||||
};
|
||||
|
||||
let mut worker = MainWorker::bootstrap_from_options(
|
||||
unused_url,
|
||||
permissions_container,
|
||||
|
|
@ -347,7 +365,7 @@ async fn start_js_runtime(
|
|||
module_loader: Rc::new(CustomModuleLoader::new(code, dev_plugin)),
|
||||
extensions: vec![plugin_ext::init_ops_and_esm(
|
||||
EventReceiver::new(event_stream),
|
||||
PluginData::new(plugin_id, plugin_uuid, inline_view_entrypoint_id),
|
||||
PluginData::new(plugin_id, plugin_uuid, inline_view_entrypoint_id, runtime_permissions),
|
||||
frontend_api,
|
||||
ComponentModel::new(component_model),
|
||||
repository,
|
||||
|
|
@ -682,15 +700,17 @@ fn from_intermediate_to_js_event(event: IntermediateUiEvent) -> JsUiEvent {
|
|||
pub struct PluginData {
|
||||
plugin_id: PluginId,
|
||||
plugin_uuid: String,
|
||||
inline_view_entrypoint_id: Option<String>
|
||||
inline_view_entrypoint_id: Option<String>,
|
||||
permissions: PluginRuntimePermissions
|
||||
}
|
||||
|
||||
impl PluginData {
|
||||
fn new(plugin_id: PluginId, plugin_uuid: String, inline_view_entrypoint_id: Option<String>) -> Self {
|
||||
fn new(plugin_id: PluginId, plugin_uuid: String, inline_view_entrypoint_id: Option<String>, permissions: PluginRuntimePermissions) -> Self {
|
||||
Self {
|
||||
plugin_id,
|
||||
plugin_uuid,
|
||||
inline_view_entrypoint_id
|
||||
inline_view_entrypoint_id,
|
||||
permissions
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -705,6 +725,10 @@ impl PluginData {
|
|||
fn inline_view_entrypoint_id(&self) -> Option<String> {
|
||||
self.inline_view_entrypoint_id.clone()
|
||||
}
|
||||
|
||||
fn permissions(&self) -> &PluginRuntimePermissions {
|
||||
&self.permissions
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ComponentModel {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use itertools::Itertools;
|
|||
use tracing_subscriber::fmt::format;
|
||||
use common::model::{DownloadStatus, PluginId};
|
||||
use crate::model::ActionShortcutKey;
|
||||
use crate::plugins::data_db_repository::{DataDbRepository, db_entrypoint_to_str, db_plugin_type_to_str, DbCode, DbPluginAction, DbPluginActionShortcutKind, DbPluginEntrypointType, DbPluginPermissions, DbPluginPreference, DbPluginPreferenceUserData, DbPluginType, DbPreferenceEnumValue, DbWritePlugin, DbWritePluginAssetData, DbWritePluginEntrypoint};
|
||||
use crate::plugins::data_db_repository::{DataDbRepository, db_entrypoint_to_str, db_plugin_type_to_str, DbCode, DbPluginAction, DbPluginActionShortcutKind, DbPluginEntrypointType, DbPluginPermissions, DbPluginPreference, DbPluginPreferenceUserData, DbPluginType, DbPreferenceEnumValue, DbWritePlugin, DbWritePluginAssetData, DbWritePluginEntrypoint, DbPluginClipboardPermissions};
|
||||
use crate::plugins::download_status::DownloadStatusHolder;
|
||||
|
||||
pub struct PluginLoader {
|
||||
|
|
@ -321,6 +321,18 @@ impl PluginLoader {
|
|||
})
|
||||
.collect();
|
||||
|
||||
let clipboard = plugin_manifest.permissions
|
||||
.clipboard
|
||||
.into_iter()
|
||||
.map(|permission| {
|
||||
match permission {
|
||||
PluginManifestClipboardPermissions::Read => DbPluginClipboardPermissions::Read,
|
||||
PluginManifestClipboardPermissions::Write => DbPluginClipboardPermissions::Write,
|
||||
PluginManifestClipboardPermissions::Clear => DbPluginClipboardPermissions::Clear,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let permissions = DbPluginPermissions {
|
||||
environment: plugin_manifest.permissions.environment,
|
||||
high_resolution_time: plugin_manifest.permissions.high_resolution_time,
|
||||
|
|
@ -330,6 +342,7 @@ impl PluginLoader {
|
|||
fs_write_access: plugin_manifest.permissions.fs_write_access,
|
||||
run_subprocess: plugin_manifest.permissions.run_subprocess,
|
||||
system: plugin_manifest.permissions.system,
|
||||
clipboard,
|
||||
};
|
||||
|
||||
Ok(PluginDownloadData {
|
||||
|
|
@ -814,4 +827,16 @@ pub struct PluginManifestPermissions {
|
|||
run_subprocess: Vec<String>,
|
||||
#[serde(default)]
|
||||
system: Vec<String>,
|
||||
#[serde(default)]
|
||||
clipboard: Vec<PluginManifestClipboardPermissions>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub enum PluginManifestClipboardPermissions {
|
||||
#[serde(rename = "read")]
|
||||
Read,
|
||||
#[serde(rename = "write")]
|
||||
Write,
|
||||
#[serde(rename = "clear")]
|
||||
Clear
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ use utils::channel::RequestSender;
|
|||
use common::dirs::Dirs;
|
||||
use crate::model::ActionShortcutKey;
|
||||
use crate::plugins::config_reader::ConfigReader;
|
||||
use crate::plugins::data_db_repository::{DataDbRepository, db_entrypoint_from_str, DbPluginActionShortcutKind, DbPluginEntrypointType, DbPluginPreference, DbPluginPreferenceUserData, DbReadPluginEntrypoint};
|
||||
use crate::plugins::data_db_repository::{DataDbRepository, db_entrypoint_from_str, DbPluginActionShortcutKind, DbPluginEntrypointType, DbPluginPreference, DbPluginPreferenceUserData, DbReadPluginEntrypoint, DbPluginClipboardPermissions};
|
||||
use crate::plugins::global_shortcut::{convert_physical_shortcut_to_hotkey, register_listener};
|
||||
use crate::plugins::icon_cache::IconCache;
|
||||
use crate::plugins::js::{AllPluginCommandData, OnePluginCommandData, PluginCode, PluginCommand, PluginPermissions, PluginRuntimeData, start_plugin_runtime};
|
||||
use crate::plugins::js::{AllPluginCommandData, OnePluginCommandData, PluginCode, PluginCommand, PluginPermissions, PluginRuntimeData, start_plugin_runtime, PluginClipboardPermissions};
|
||||
use crate::plugins::loader::PluginLoader;
|
||||
use crate::plugins::run_status::RunStatusHolder;
|
||||
use crate::search::SearchIndex;
|
||||
|
|
@ -553,6 +553,17 @@ impl ApplicationManager {
|
|||
.await?;
|
||||
|
||||
let receiver = self.command_broadcaster.subscribe();
|
||||
|
||||
let clipboard_permissions = plugin.permissions
|
||||
.clipboard
|
||||
.into_iter()
|
||||
.map(|permission| match permission {
|
||||
DbPluginClipboardPermissions::Read => PluginClipboardPermissions::Read,
|
||||
DbPluginClipboardPermissions::Write => PluginClipboardPermissions::Write,
|
||||
DbPluginClipboardPermissions::Clear => PluginClipboardPermissions::Clear,
|
||||
})
|
||||
.collect();
|
||||
|
||||
let data = PluginRuntimeData {
|
||||
id: plugin_id,
|
||||
uuid: plugin.uuid,
|
||||
|
|
@ -566,7 +577,8 @@ impl ApplicationManager {
|
|||
fs_read_access: plugin.permissions.fs_read_access,
|
||||
fs_write_access: plugin.permissions.fs_write_access,
|
||||
run_subprocess: plugin.permissions.run_subprocess,
|
||||
system: plugin.permissions.system
|
||||
system: plugin.permissions.system,
|
||||
clipboard: clipboard_permissions,
|
||||
},
|
||||
command_receiver: receiver,
|
||||
db_repository: self.db_repository.clone(),
|
||||
|
|
|
|||
2
tools
2
tools
|
|
@ -1 +1 @@
|
|||
Subproject commit d85ac747727320956a20ee5d50505ad7fff61db0
|
||||
Subproject commit 23709487f8e98709fe3f5d03cb2a143a62026dca
|
||||
Loading…
Add table
Add a link
Reference in a new issue