use crate::permissions::NetworkPermissions;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use wasmtime::component::ResourceTable;
use wasmtime_wasi::p2::{IoView, WasiCtx, WasiView};
pub struct WasiState {
pub ctx: WasiCtx,
pub table: ResourceTable,
pub plugin_host: PluginHost,
pub repl_vars: Arc<Mutex<HashMap<String, String>>>,
pub plugins_names: Vec<String>,
}
pub struct PluginHost {
pub network_permissions: NetworkPermissions,
pub repl_vars: Arc<Mutex<HashMap<String, String>>>,
}
impl crate::api::plugin_api::repl::api::http_client::Host for PluginHost {
async fn get(
&mut self,
url: String,
_headers: Vec<crate::api::plugin_api::repl::api::http_client::HttpHeader>, ) -> Result<crate::api::plugin_api::repl::api::http_client::HttpResponse, String> {
let hostname = crate::helpers::extract_hostname(&url);
if !self.network_permissions.is_allowed(&hostname) {
return Err(format!(
"PermissionDenied: network access to {} is not allowed",
hostname
));
}
let response = reqwest::Client::new()
.get(url)
.send()
.await
.map_err(|e| e.to_string())?;
Ok(
crate::api::plugin_api::repl::api::http_client::HttpResponse {
status: response.status().as_u16(),
ok: response.status().is_success(),
headers: response
.headers()
.iter()
.map(
|(k, v)| crate::api::plugin_api::repl::api::http_client::HttpHeader {
name: k.to_string(),
value: v.to_str().unwrap().to_string(),
},
)
.collect(),
body: response.text().await.map_err(|e| e.to_string())?,
},
)
}
}
impl crate::api::plugin_api::repl::api::host_state_plugin::Host for PluginHost {
async fn get_repl_var(&mut self, key: String) -> Option<String> {
self.repl_vars
.lock()
.expect("Failed to acquire repl_vars lock")
.get(&key)
.cloned()
}
}
impl crate::api::plugin_api::repl::api::transport::Host for PluginHost {
}
impl crate::api::host_api::repl::api::transport::Host for WasiState {
}
impl IoView for WasiState {
fn table(&mut self) -> &mut ResourceTable {
&mut self.table
}
}
impl WasiView for WasiState {
fn ctx(&mut self) -> &mut WasiCtx {
&mut self.ctx
}
}
impl crate::api::host_api::repl::api::host_state::Host for WasiState {
async fn get_plugins_names(&mut self) -> wasmtime::component::__internal::Vec<String> {
self.plugins_names.clone()
}
async fn get_repl_vars(
&mut self,
) -> wasmtime::component::__internal::Vec<crate::api::host_api::repl::api::transport::ReplVar>
{
self.repl_vars
.lock()
.expect("Failed to acquire repl_vars lock")
.iter()
.map(
|(key, value)| crate::api::host_api::repl::api::transport::ReplVar {
key: key.clone(),
value: value.clone(),
},
)
.collect()
}
async fn set_repl_var(&mut self, var: crate::api::host_api::repl::api::transport::ReplVar) {
self.repl_vars
.lock()
.expect("Failed to acquire repl_vars lock")
.insert(var.key.clone(), var.value.clone());
}
}