mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-24 18:31:16 +01:00
[WIP] Encryption for secure values (#183)
This commit is contained in:
@@ -5,6 +5,12 @@ use tokio::sync::mpsc::error::SendError;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error(transparent)]
|
||||
CryptoErr(#[from] yaak_crypto::error::Error),
|
||||
|
||||
#[error(transparent)]
|
||||
TemplateErr(#[from] yaak_templates::error::Error),
|
||||
|
||||
#[error("IO error: {0}")]
|
||||
IoErr(#[from] io::Error),
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use tauri::{Runtime, WebviewWindow};
|
||||
use ts_rs::TS;
|
||||
|
||||
use yaak_common::window::WorkspaceWindowTrait;
|
||||
use yaak_models::models::{
|
||||
Environment, Folder, GrpcRequest, HttpRequest, HttpResponse, WebsocketRequest, Workspace,
|
||||
};
|
||||
@@ -15,7 +15,7 @@ pub struct InternalEvent {
|
||||
pub plugin_ref_id: String,
|
||||
pub plugin_name: String,
|
||||
pub reply_id: Option<String>,
|
||||
pub window_context: WindowContext,
|
||||
pub window_context: PluginWindowContext,
|
||||
pub payload: InternalEventPayload,
|
||||
}
|
||||
|
||||
@@ -29,22 +29,32 @@ pub(crate) struct InternalEventRawPayload {
|
||||
pub plugin_ref_id: String,
|
||||
pub plugin_name: String,
|
||||
pub reply_id: Option<String>,
|
||||
pub window_context: WindowContext,
|
||||
pub window_context: PluginWindowContext,
|
||||
pub payload: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
|
||||
#[serde(rename_all = "snake_case", tag = "type")]
|
||||
#[ts(export, export_to = "gen_events.ts")]
|
||||
pub enum WindowContext {
|
||||
pub enum PluginWindowContext {
|
||||
None,
|
||||
Label { label: String },
|
||||
Label {
|
||||
label: String,
|
||||
workspace_id: Option<String>,
|
||||
},
|
||||
}
|
||||
|
||||
impl WindowContext {
|
||||
pub fn from_window<R: Runtime>(window: &WebviewWindow<R>) -> Self {
|
||||
impl PluginWindowContext {
|
||||
pub fn new<R: Runtime>(window: &WebviewWindow<R>) -> Self {
|
||||
Self::Label {
|
||||
label: window.label().to_string(),
|
||||
workspace_id: window.workspace_id(),
|
||||
}
|
||||
}
|
||||
pub fn new_no_workspace<R: Runtime>(window: &WebviewWindow<R>) -> Self {
|
||||
Self::Label {
|
||||
label: window.label().to_string(),
|
||||
workspace_id: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -497,7 +507,15 @@ pub struct TemplateFunction {
|
||||
/// tags when changing the `name` property
|
||||
#[ts(optional)]
|
||||
pub aliases: Option<Vec<String>>,
|
||||
pub args: Vec<FormInput>,
|
||||
pub args: Vec<TemplateFunctionArg>,
|
||||
}
|
||||
|
||||
/// Similar to FormInput, but contains
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
|
||||
#[serde(rename_all = "snake_case", untagged)]
|
||||
#[ts(export, export_to = "gen_events.ts")]
|
||||
pub enum TemplateFunctionArg {
|
||||
FormInput(FormInput),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
|
||||
|
||||
@@ -7,10 +7,11 @@ use tauri::{Manager, RunEvent, Runtime, State};
|
||||
pub mod error;
|
||||
pub mod events;
|
||||
pub mod manager;
|
||||
pub mod plugin_handle;
|
||||
pub mod template_callback;
|
||||
pub mod native_template_functions;
|
||||
mod nodejs;
|
||||
pub mod plugin_handle;
|
||||
mod server_ws;
|
||||
pub mod template_callback;
|
||||
mod util;
|
||||
|
||||
pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
@@ -18,7 +19,6 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
.setup(|app_handle, _| {
|
||||
let manager = PluginManager::new(app_handle.clone());
|
||||
app_handle.manage(manager.clone());
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.on_event(|app, e| match e {
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::events::{
|
||||
EmptyPayload, FilterRequest, FilterResponse, GetHttpAuthenticationConfigRequest,
|
||||
GetHttpAuthenticationConfigResponse, GetHttpAuthenticationSummaryResponse,
|
||||
GetHttpRequestActionsResponse, GetTemplateFunctionsResponse, ImportRequest, ImportResponse,
|
||||
InternalEvent, InternalEventPayload, JsonPrimitive, RenderPurpose, WindowContext,
|
||||
InternalEvent, InternalEventPayload, JsonPrimitive, PluginWindowContext, RenderPurpose,
|
||||
};
|
||||
use crate::nodejs::start_nodejs_plugin_runtime;
|
||||
use crate::plugin_handle::PluginHandle;
|
||||
@@ -30,6 +30,7 @@ use yaak_models::query_manager::QueryManagerExt;
|
||||
use yaak_models::util::generate_id;
|
||||
use yaak_templates::error::Error::RenderError;
|
||||
use yaak_templates::error::Result as TemplateResult;
|
||||
use crate::native_template_functions::template_function_secure;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PluginManager {
|
||||
@@ -100,7 +101,7 @@ impl PluginManager {
|
||||
Ok(_) => {
|
||||
info!("Plugin runtime client connected!");
|
||||
plugin_manager
|
||||
.initialize_all_plugins(&app_handle, &WindowContext::None)
|
||||
.initialize_all_plugins(&app_handle, &PluginWindowContext::None)
|
||||
.await
|
||||
.expect("Failed to reload plugins");
|
||||
}
|
||||
@@ -172,14 +173,14 @@ impl PluginManager {
|
||||
[bundled_plugin_dirs, installed_plugin_dirs].concat()
|
||||
}
|
||||
|
||||
pub async fn uninstall(&self, window_context: &WindowContext, dir: &str) -> Result<()> {
|
||||
pub async fn uninstall(&self, window_context: &PluginWindowContext, dir: &str) -> Result<()> {
|
||||
let plugin = self.get_plugin_by_dir(dir).await.ok_or(PluginNotFoundErr(dir.to_string()))?;
|
||||
self.remove_plugin(window_context, &plugin).await
|
||||
}
|
||||
|
||||
async fn remove_plugin(
|
||||
&self,
|
||||
window_context: &WindowContext,
|
||||
window_context: &PluginWindowContext,
|
||||
plugin: &PluginHandle,
|
||||
) -> Result<()> {
|
||||
// Terminate the plugin
|
||||
@@ -197,7 +198,7 @@ impl PluginManager {
|
||||
|
||||
pub async fn add_plugin_by_dir(
|
||||
&self,
|
||||
window_context: &WindowContext,
|
||||
window_context: &PluginWindowContext,
|
||||
dir: &str,
|
||||
watch: bool,
|
||||
) -> Result<()> {
|
||||
@@ -240,7 +241,7 @@ impl PluginManager {
|
||||
pub async fn initialize_all_plugins<R: Runtime>(
|
||||
&self,
|
||||
app_handle: &AppHandle<R>,
|
||||
window_context: &WindowContext,
|
||||
window_context: &PluginWindowContext,
|
||||
) -> Result<()> {
|
||||
let start = Instant::now();
|
||||
let candidates = self.list_plugin_dirs(app_handle).await;
|
||||
@@ -325,7 +326,7 @@ impl PluginManager {
|
||||
|
||||
async fn send_to_plugin_and_wait(
|
||||
&self,
|
||||
window_context: &WindowContext,
|
||||
window_context: &PluginWindowContext,
|
||||
plugin: &PluginHandle,
|
||||
payload: &InternalEventPayload,
|
||||
) -> Result<InternalEvent> {
|
||||
@@ -336,7 +337,7 @@ impl PluginManager {
|
||||
|
||||
async fn send_and_wait(
|
||||
&self,
|
||||
window_context: &WindowContext,
|
||||
window_context: &PluginWindowContext,
|
||||
payload: &InternalEventPayload,
|
||||
) -> Result<Vec<InternalEvent>> {
|
||||
let plugins = { self.plugins.lock().await.clone() };
|
||||
@@ -345,7 +346,7 @@ impl PluginManager {
|
||||
|
||||
async fn send_to_plugins_and_wait(
|
||||
&self,
|
||||
window_context: &WindowContext,
|
||||
window_context: &PluginWindowContext,
|
||||
payload: &InternalEventPayload,
|
||||
plugins: Vec<PluginHandle>,
|
||||
) -> Result<Vec<InternalEvent>> {
|
||||
@@ -408,7 +409,7 @@ impl PluginManager {
|
||||
) -> Result<Vec<GetHttpRequestActionsResponse>> {
|
||||
let reply_events = self
|
||||
.send_and_wait(
|
||||
&WindowContext::from_window(window),
|
||||
&PluginWindowContext::new(window),
|
||||
&InternalEventPayload::GetHttpRequestActionsRequest(EmptyPayload {}),
|
||||
)
|
||||
.await?;
|
||||
@@ -427,25 +428,31 @@ impl PluginManager {
|
||||
&self,
|
||||
window: &WebviewWindow<R>,
|
||||
) -> Result<Vec<GetTemplateFunctionsResponse>> {
|
||||
self.get_template_functions_with_context(&WindowContext::from_window(window)).await
|
||||
self.get_template_functions_with_context(&PluginWindowContext::new(&window)).await
|
||||
}
|
||||
|
||||
pub async fn get_template_functions_with_context(
|
||||
&self,
|
||||
window_context: &WindowContext,
|
||||
window_context: &PluginWindowContext,
|
||||
) -> Result<Vec<GetTemplateFunctionsResponse>> {
|
||||
let reply_events = self
|
||||
.send_and_wait(window_context, &InternalEventPayload::GetTemplateFunctionsRequest)
|
||||
.await?;
|
||||
|
||||
let mut all_actions = Vec::new();
|
||||
let mut result = Vec::new();
|
||||
for event in reply_events {
|
||||
if let InternalEventPayload::GetTemplateFunctionsResponse(resp) = event.payload {
|
||||
all_actions.push(resp.clone());
|
||||
result.push(resp.clone());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(all_actions)
|
||||
// Add Rust-based functions
|
||||
result.push(GetTemplateFunctionsResponse {
|
||||
plugin_ref_id: "__NATIVE__".to_string(), // Meh
|
||||
functions: vec![template_function_secure()],
|
||||
});
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub async fn call_http_request_action<R: Runtime>(
|
||||
@@ -457,7 +464,7 @@ impl PluginManager {
|
||||
let plugin =
|
||||
self.get_plugin_by_ref_id(ref_id.as_str()).await.ok_or(PluginNotFoundErr(ref_id))?;
|
||||
let event = plugin.build_event_to_send(
|
||||
&WindowContext::from_window(window),
|
||||
&PluginWindowContext::new(window),
|
||||
&InternalEventPayload::CallHttpRequestActionRequest(req),
|
||||
None,
|
||||
);
|
||||
@@ -469,7 +476,7 @@ impl PluginManager {
|
||||
&self,
|
||||
window: &WebviewWindow<R>,
|
||||
) -> Result<Vec<(PluginHandle, GetHttpAuthenticationSummaryResponse)>> {
|
||||
let window_context = WindowContext::from_window(window);
|
||||
let window_context = PluginWindowContext::new(window);
|
||||
let reply_events = self
|
||||
.send_and_wait(
|
||||
&window_context,
|
||||
@@ -508,7 +515,7 @@ impl PluginManager {
|
||||
let context_id = format!("{:x}", md5::compute(request_id.to_string()));
|
||||
let event = self
|
||||
.send_to_plugin_and_wait(
|
||||
&WindowContext::from_window(window),
|
||||
&PluginWindowContext::new(window),
|
||||
&plugin,
|
||||
&InternalEventPayload::GetHttpAuthenticationConfigRequest(
|
||||
GetHttpAuthenticationConfigRequest { values, context_id },
|
||||
@@ -540,7 +547,7 @@ impl PluginManager {
|
||||
|
||||
let context_id = format!("{:x}", md5::compute(request_id.to_string()));
|
||||
self.send_to_plugin_and_wait(
|
||||
&WindowContext::from_window(window),
|
||||
&PluginWindowContext::new(window),
|
||||
&plugin,
|
||||
&InternalEventPayload::CallHttpAuthenticationActionRequest(
|
||||
CallHttpAuthenticationActionRequest {
|
||||
@@ -581,7 +588,7 @@ impl PluginManager {
|
||||
|
||||
let event = self
|
||||
.send_to_plugin_and_wait(
|
||||
&WindowContext::from_window(window),
|
||||
&PluginWindowContext::new(window),
|
||||
&plugin,
|
||||
&InternalEventPayload::CallHttpAuthenticationRequest(req),
|
||||
)
|
||||
@@ -597,7 +604,7 @@ impl PluginManager {
|
||||
|
||||
pub async fn call_template_function(
|
||||
&self,
|
||||
window_context: &WindowContext,
|
||||
window_context: &PluginWindowContext,
|
||||
fn_name: &str,
|
||||
args: HashMap<String, String>,
|
||||
purpose: RenderPurpose,
|
||||
@@ -636,7 +643,7 @@ impl PluginManager {
|
||||
) -> Result<ImportResponse> {
|
||||
let reply_events = self
|
||||
.send_and_wait(
|
||||
&WindowContext::from_window(window),
|
||||
&PluginWindowContext::new(window),
|
||||
&InternalEventPayload::ImportRequest(ImportRequest {
|
||||
content: content.to_string(),
|
||||
}),
|
||||
@@ -675,7 +682,7 @@ impl PluginManager {
|
||||
|
||||
let event = self
|
||||
.send_to_plugin_and_wait(
|
||||
&WindowContext::from_window(window),
|
||||
&PluginWindowContext::new(window),
|
||||
&plugin,
|
||||
&InternalEventPayload::FilterRequest(FilterRequest {
|
||||
filter: filter.to_string(),
|
||||
|
||||
164
src-tauri/yaak-plugins/src/native_template_functions.rs
Normal file
164
src-tauri/yaak-plugins/src/native_template_functions.rs
Normal file
@@ -0,0 +1,164 @@
|
||||
use crate::events::{
|
||||
FormInput, FormInputBase, FormInputText, PluginWindowContext, RenderPurpose, TemplateFunction,
|
||||
TemplateFunctionArg,
|
||||
};
|
||||
use crate::template_callback::PluginTemplateCallback;
|
||||
use base64::Engine;
|
||||
use base64::prelude::BASE64_STANDARD;
|
||||
use std::collections::HashMap;
|
||||
use tauri::{AppHandle, Runtime};
|
||||
use yaak_crypto::manager::EncryptionManagerExt;
|
||||
use yaak_templates::error::Error::RenderError;
|
||||
use yaak_templates::error::Result;
|
||||
use yaak_templates::{FnArg, Parser, Token, Tokens, Val, transform_args};
|
||||
|
||||
pub(crate) fn template_function_secure() -> TemplateFunction {
|
||||
TemplateFunction {
|
||||
name: "secure".to_string(),
|
||||
description: Some("Securely store encrypted text".to_string()),
|
||||
aliases: None,
|
||||
args: vec![TemplateFunctionArg::FormInput(FormInput::Text(
|
||||
FormInputText {
|
||||
multi_line: Some(true),
|
||||
password: Some(true),
|
||||
base: FormInputBase {
|
||||
name: "value".to_string(),
|
||||
label: Some("Value".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
))],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn template_function_secure_run<R: Runtime>(
|
||||
app_handle: &AppHandle<R>,
|
||||
args: HashMap<String, String>,
|
||||
window_context: &PluginWindowContext,
|
||||
) -> Result<String> {
|
||||
match window_context.clone() {
|
||||
PluginWindowContext::Label {
|
||||
workspace_id: Some(wid),
|
||||
..
|
||||
} => {
|
||||
let value = args.get("value").map(|v| v.to_owned()).unwrap_or_default();
|
||||
if value.is_empty() {
|
||||
return Ok("".to_string());
|
||||
}
|
||||
|
||||
let value = match value.strip_prefix("YENC_") {
|
||||
None => {
|
||||
return Err(RenderError("Could not decrypt non-encrypted value".to_string()));
|
||||
}
|
||||
Some(v) => v,
|
||||
};
|
||||
|
||||
let value = BASE64_STANDARD.decode(&value).unwrap();
|
||||
let r = match app_handle.crypto().decrypt(&wid, value.as_slice()) {
|
||||
Ok(r) => Ok(r),
|
||||
Err(e) => Err(RenderError(e.to_string())),
|
||||
}?;
|
||||
let r = String::from_utf8(r).map_err(|e| RenderError(e.to_string()))?;
|
||||
Ok(r)
|
||||
}
|
||||
_ => Err(RenderError("workspace_id missing from window context".to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn template_function_secure_transform_arg<R: Runtime>(
|
||||
app_handle: &AppHandle<R>,
|
||||
window_context: &PluginWindowContext,
|
||||
arg_name: &str,
|
||||
arg_value: &str,
|
||||
) -> Result<String> {
|
||||
if arg_name != "value" {
|
||||
return Ok(arg_value.to_string());
|
||||
}
|
||||
|
||||
match window_context.clone() {
|
||||
PluginWindowContext::Label {
|
||||
workspace_id: Some(wid),
|
||||
..
|
||||
} => {
|
||||
if arg_value.is_empty() {
|
||||
return Ok("".to_string());
|
||||
}
|
||||
|
||||
if arg_value.starts_with("YENC_") {
|
||||
// Already encrypted, so do nothing
|
||||
return Ok(arg_value.to_string());
|
||||
}
|
||||
|
||||
let r = app_handle
|
||||
.crypto()
|
||||
.encrypt(&wid, arg_value.as_bytes())
|
||||
.map_err(|e| RenderError(e.to_string()))?;
|
||||
let r = BASE64_STANDARD.encode(r);
|
||||
Ok(format!("YENC_{}", r))
|
||||
}
|
||||
_ => Err(RenderError("workspace_id missing from window context".to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decrypt_secure_template_function<R: Runtime>(
|
||||
app_handle: &AppHandle<R>,
|
||||
window_context: &PluginWindowContext,
|
||||
template: &str,
|
||||
) -> Result<String> {
|
||||
let mut parsed = Parser::new(template).parse()?;
|
||||
let mut new_tokens: Vec<Token> = Vec::new();
|
||||
|
||||
for token in parsed.tokens.iter() {
|
||||
match token {
|
||||
Token::Tag {
|
||||
val: Val::Fn { name, args },
|
||||
} if name == "secure" => {
|
||||
let mut args_map = HashMap::new();
|
||||
for a in args {
|
||||
match a.clone().value {
|
||||
Val::Str { text } => {
|
||||
args_map.insert(a.name.to_string(), text);
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
new_tokens.push(Token::Raw {
|
||||
text: template_function_secure_run(app_handle, args_map, window_context)?,
|
||||
});
|
||||
}
|
||||
t => {
|
||||
new_tokens.push(t.clone());
|
||||
continue;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
parsed.tokens = new_tokens;
|
||||
Ok(parsed.to_string())
|
||||
}
|
||||
|
||||
pub fn encrypt_secure_template_function<R: Runtime>(
|
||||
app_handle: &AppHandle<R>,
|
||||
window_context: &PluginWindowContext,
|
||||
template: &str,
|
||||
) -> Result<String> {
|
||||
let decrypted = decrypt_secure_template_function(&app_handle, window_context, template)?;
|
||||
let tokens = Tokens {
|
||||
tokens: vec![Token::Tag {
|
||||
val: Val::Fn {
|
||||
name: "secure".to_string(),
|
||||
args: vec![FnArg {
|
||||
name: "value".to_string(),
|
||||
value: Val::Str { text: decrypted },
|
||||
}],
|
||||
},
|
||||
}],
|
||||
};
|
||||
|
||||
Ok(transform_args(
|
||||
tokens,
|
||||
&PluginTemplateCallback::new(app_handle, window_context, RenderPurpose::Preview),
|
||||
)?
|
||||
.to_string())
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::error::Result;
|
||||
use crate::events::{BootResponse, InternalEvent, InternalEventPayload, WindowContext};
|
||||
use crate::events::{BootResponse, InternalEvent, InternalEventPayload, PluginWindowContext};
|
||||
use crate::util::gen_id;
|
||||
use log::info;
|
||||
use std::path::Path;
|
||||
@@ -37,7 +37,7 @@ impl PluginHandle {
|
||||
|
||||
pub fn build_event_to_send(
|
||||
&self,
|
||||
window_context: &WindowContext,
|
||||
window_context: &PluginWindowContext,
|
||||
payload: &InternalEventPayload,
|
||||
reply_id: Option<String>,
|
||||
) -> InternalEvent {
|
||||
@@ -46,7 +46,7 @@ impl PluginHandle {
|
||||
|
||||
pub(crate) fn build_event_to_send_raw(
|
||||
&self,
|
||||
window_context: &WindowContext,
|
||||
window_context: &PluginWindowContext,
|
||||
payload: &InternalEventPayload,
|
||||
reply_id: Option<String>,
|
||||
) -> InternalEvent {
|
||||
@@ -61,7 +61,7 @@ impl PluginHandle {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn terminate(&self, window_context: &WindowContext) -> Result<()> {
|
||||
pub async fn terminate(&self, window_context: &PluginWindowContext) -> Result<()> {
|
||||
info!("Terminating plugin {}", self.dir);
|
||||
let event =
|
||||
self.build_event_to_send(window_context, &InternalEventPayload::TerminateRequest, None);
|
||||
|
||||
@@ -1,40 +1,46 @@
|
||||
use crate::events::{RenderPurpose, WindowContext};
|
||||
use crate::events::{PluginWindowContext, RenderPurpose};
|
||||
use crate::manager::PluginManager;
|
||||
use crate::native_template_functions::{
|
||||
template_function_secure_run, template_function_secure_transform_arg,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use tauri::{AppHandle, Manager, Runtime};
|
||||
use yaak_templates::error::Result;
|
||||
use yaak_templates::TemplateCallback;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PluginTemplateCallback {
|
||||
plugin_manager: PluginManager,
|
||||
window_context: WindowContext,
|
||||
pub struct PluginTemplateCallback<R: Runtime> {
|
||||
app_handle: AppHandle<R>,
|
||||
render_purpose: RenderPurpose,
|
||||
window_context: PluginWindowContext,
|
||||
}
|
||||
|
||||
impl PluginTemplateCallback {
|
||||
pub fn new<R: Runtime>(
|
||||
impl<R: Runtime> PluginTemplateCallback<R> {
|
||||
pub fn new(
|
||||
app_handle: &AppHandle<R>,
|
||||
window_context: &WindowContext,
|
||||
window_context: &PluginWindowContext,
|
||||
render_purpose: RenderPurpose,
|
||||
) -> PluginTemplateCallback {
|
||||
let plugin_manager = &*app_handle.state::<PluginManager>();
|
||||
) -> PluginTemplateCallback<R> {
|
||||
PluginTemplateCallback {
|
||||
plugin_manager: plugin_manager.to_owned(),
|
||||
window_context: window_context.to_owned(),
|
||||
render_purpose,
|
||||
app_handle: app_handle.to_owned(),
|
||||
window_context: window_context.to_owned(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TemplateCallback for PluginTemplateCallback {
|
||||
impl<R: Runtime> TemplateCallback for PluginTemplateCallback<R> {
|
||||
async fn run(&self, fn_name: &str, args: HashMap<String, String>) -> Result<String> {
|
||||
// The beta named the function `Response` but was changed in stable.
|
||||
// Keep this here for a while because there's no easy way to migrate
|
||||
let fn_name = if fn_name == "Response" { "response" } else { fn_name };
|
||||
|
||||
let resp = self
|
||||
.plugin_manager
|
||||
if fn_name == "secure" {
|
||||
return template_function_secure_run(&self.app_handle, args, &self.window_context);
|
||||
}
|
||||
|
||||
let plugin_manager = &*self.app_handle.state::<PluginManager>();
|
||||
let resp = plugin_manager
|
||||
.call_template_function(
|
||||
&self.window_context,
|
||||
fn_name,
|
||||
@@ -44,4 +50,22 @@ impl TemplateCallback for PluginTemplateCallback {
|
||||
.await?;
|
||||
Ok(resp)
|
||||
}
|
||||
|
||||
fn transform_arg(
|
||||
&self,
|
||||
fn_name: &str,
|
||||
arg_name: &str,
|
||||
arg_value: &str,
|
||||
) -> Result<String> {
|
||||
if fn_name == "secure" {
|
||||
return template_function_secure_transform_arg(
|
||||
&self.app_handle,
|
||||
&self.window_context,
|
||||
arg_name,
|
||||
arg_value,
|
||||
);
|
||||
}
|
||||
|
||||
Ok(arg_value.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user