Delete src/plugins/bad-sandbox.rs
This commit is contained in:
parent
c5ec1d432b
commit
fafa454c24
@ -1,311 +0,0 @@
|
||||
//! Песочница Lua для безопасного выполнения плагинов
|
||||
|
||||
use std::path::Path;
|
||||
use mlua::{Lua, Value as LuaValue, Result as LuaResult, Error as LuaError};
|
||||
use serde_json::{Value, json};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::plugins::traits::{PluginEvent, PluginHook, PluginState};
|
||||
use crate::plugins::channel::PluginInfo;
|
||||
|
||||
/// Песочница Lua для изоляции плагинов
|
||||
pub struct LuaSandbox {
|
||||
lua: Lua,
|
||||
plugin_id: String,
|
||||
hooks: Vec<PluginHook>,
|
||||
}
|
||||
|
||||
impl LuaSandbox {
|
||||
/// Создать новую песочницу
|
||||
pub fn new() -> Result<Self, String> {
|
||||
let lua = Lua::new();
|
||||
|
||||
// Настройка безопасного окружения
|
||||
let globals = lua.globals();
|
||||
|
||||
// Ограничиваем доступ к опасным функциям
|
||||
globals.set("os", LuaValue::Nil)
|
||||
.map_err(|e| format!("Failed to restrict os: {}", e))?;
|
||||
|
||||
globals.set("io", LuaValue::Nil)
|
||||
.map_err(|e| format!("Failed to restrict io: {}", e))?;
|
||||
|
||||
globals.set("debug", LuaValue::Nil)
|
||||
.map_err(|e| format!("Failed to restrict debug: {}", e))?;
|
||||
|
||||
globals.set("load", LuaValue::Nil)
|
||||
.map_err(|e| format!("Failed to restrict load: {}", e))?;
|
||||
|
||||
globals.set("loadfile", LuaValue::Nil)
|
||||
.map_err(|e| format!("Failed to restrict loadfile: {}", e))?;
|
||||
|
||||
globals.set("dofile", LuaValue::Nil)
|
||||
.map_err(|e| format!("Failed to restrict dofile: {}", e))?;
|
||||
|
||||
// Добавляем безопасные функции
|
||||
Self::register_safe_functions(&lua)
|
||||
.map_err(|e| format!("Failed to register safe functions: {}", e))?;
|
||||
|
||||
Ok(Self {
|
||||
lua,
|
||||
plugin_id: String::new(),
|
||||
hooks: Vec::new(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Зарегистрировать безопасные функции
|
||||
fn register_safe_functions(lua: &Lua) -> LuaResult<()> {
|
||||
let globals = lua.globals();
|
||||
|
||||
// Безопасные функции для логирования
|
||||
let log_table = lua.create_table()?;
|
||||
|
||||
let lua_clone = lua.clone();
|
||||
log_table.set("info", lua.create_function(move |_, msg: String| {
|
||||
log::info!("[Plugin] {}", msg);
|
||||
Ok(())
|
||||
})?)?;
|
||||
|
||||
let lua_clone = lua.clone();
|
||||
log_table.set("error", lua.create_function(move |_, msg: String| {
|
||||
log::error!("[Plugin] {}", msg);
|
||||
Ok(())
|
||||
})?)?;
|
||||
|
||||
let lua_clone = lua.clone();
|
||||
log_table.set("warn", lua.create_function(move |_, msg: String| {
|
||||
log::warn!("[Plugin] {}", msg);
|
||||
Ok(())
|
||||
})?)?;
|
||||
|
||||
let lua_clone = lua.clone();
|
||||
log_table.set("debug", lua.create_function(move |_, msg: String| {
|
||||
log::debug!("[Plugin] {}", msg);
|
||||
Ok(())
|
||||
})?)?;
|
||||
|
||||
globals.set("log", log_table)?;
|
||||
|
||||
// Функция для работы с JSON
|
||||
let json_table = lua.create_table()?;
|
||||
|
||||
let lua_clone = lua.clone();
|
||||
json_table.set("encode", lua.create_function(move |lua, value: LuaValue| {
|
||||
let json_value = Self::lua_value_to_json(value)?;
|
||||
let json_str = serde_json::to_string(&json_value)
|
||||
.map_err(|e| LuaError::external(e))?;
|
||||
Ok(json_str)
|
||||
})?)?;
|
||||
|
||||
let lua_clone = lua.clone();
|
||||
json_table.set("decode", lua.create_function(move |lua, json_str: String| {
|
||||
let json_value: Value = serde_json::from_str(&json_str)
|
||||
.map_err(|e| LuaError::external(e))?;
|
||||
Self::json_to_lua_value(lua, json_value)
|
||||
})?)?;
|
||||
|
||||
globals.set("json", json_table)?;
|
||||
|
||||
// Функция для генерации UUID
|
||||
let lua_clone = lua.clone();
|
||||
globals.set("uuid", lua.create_function(move |_, ()| {
|
||||
Ok(Uuid::new_v4().to_string())
|
||||
})?)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Загрузить плагин из кода
|
||||
pub fn load_plugin(&mut self, code: &str, path: &str) -> Result<PluginInfo, String> {
|
||||
// Выполняем код плагина
|
||||
self.lua.load(code).exec()
|
||||
.map_err(|e| format!("Failed to execute plugin code: {}", e))?;
|
||||
|
||||
// Получаем метаданные плагина
|
||||
let globals = self.lua.globals();
|
||||
|
||||
let plugin_table: mlua::Table = globals.get("PLUGIN")
|
||||
.map_err(|_| "PLUGIN table not found".to_string())?;
|
||||
|
||||
let name: String = plugin_table.get("name")
|
||||
.map_err(|e| format!("Failed to get plugin name: {}", e))?;
|
||||
|
||||
let version: String = plugin_table.get("version")
|
||||
.map_err(|e| format!("Failed to get plugin version: {}", e))?;
|
||||
|
||||
let description: String = plugin_table.get("description")
|
||||
.unwrap_or_else(|_| "No description".to_string());
|
||||
|
||||
let author: String = plugin_table.get("author")
|
||||
.unwrap_or_else(|_| "Unknown".to_string());
|
||||
|
||||
// Генерируем ID плагина
|
||||
let plugin_id = format!("{}-{}", name, Uuid::new_v4());
|
||||
self.plugin_id = plugin_id.clone();
|
||||
|
||||
// Получаем хуки
|
||||
let hooks_table: mlua::Table = plugin_table.get("hooks")
|
||||
.unwrap_or_else(|_| self.lua.create_table().unwrap());
|
||||
|
||||
let mut hooks = Vec::new();
|
||||
|
||||
for pair in hooks_table.pairs::<String, mlua::Table>() {
|
||||
match pair {
|
||||
Ok((hook_name, hook_table)) => {
|
||||
let function: String = hook_table.get("function")
|
||||
.unwrap_or_else(|_| hook_name.clone());
|
||||
|
||||
let priority: u32 = hook_table.get("priority")
|
||||
.unwrap_or(100);
|
||||
|
||||
let async_hook: bool = hook_table.get("async")
|
||||
.unwrap_or(false);
|
||||
|
||||
hooks.push(PluginHook {
|
||||
name: hook_name,
|
||||
function,
|
||||
priority,
|
||||
async_hook,
|
||||
});
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("Failed to parse hook: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.hooks = hooks.clone();
|
||||
|
||||
Ok(PluginInfo {
|
||||
id: plugin_id,
|
||||
name,
|
||||
version,
|
||||
description,
|
||||
author,
|
||||
path: path.to_string(),
|
||||
state: format!("{:?}", PluginState::Loaded),
|
||||
hooks,
|
||||
})
|
||||
}
|
||||
|
||||
/// Обработать событие
|
||||
pub fn handle_event(&self, event: &PluginEvent) -> Result<(), String> {
|
||||
let globals = self.lua.globals();
|
||||
|
||||
// Проверяем, есть ли функция для обработки событий
|
||||
if let Ok(on_event) = globals.get::<_, mlua::Function>("on_event") {
|
||||
let event_data = json!({
|
||||
"type": format!("{:?}", event.event_type),
|
||||
"data": event.data,
|
||||
"source": event.source,
|
||||
"timestamp": event.timestamp,
|
||||
});
|
||||
|
||||
let event_json = serde_json::to_string(&event_data)
|
||||
.map_err(|e| format!("Failed to serialize event: {}", e))?;
|
||||
|
||||
on_event.call::<_, ()>(event_json)
|
||||
.map_err(|e| format!("Failed to call on_event: {}", e))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Выполнить хук
|
||||
pub fn execute_hook(&self, function_name: &str, data: Value) -> Result<Value, String> {
|
||||
let globals = self.lua.globals();
|
||||
|
||||
// Получаем функцию по имени
|
||||
let hook_func: mlua::Function = globals.get(function_name)
|
||||
.map_err(|e| format!("Hook function not found: {} - {}", function_name, e))?;
|
||||
|
||||
// Преобразуем данные в Lua значение
|
||||
let lua_data = Self::json_to_lua_value(&self.lua, data)
|
||||
.map_err(|e| format!("Failed to convert data to Lua: {}", e))?;
|
||||
|
||||
// Вызываем функцию
|
||||
let result = hook_func.call::<_, LuaValue>(lua_data)
|
||||
.map_err(|e| format!("Failed to execute hook: {}", e))?;
|
||||
|
||||
// Преобразуем результат обратно в JSON
|
||||
Self::lua_value_to_json(result)
|
||||
.map_err(|e| format!("Failed to convert result to JSON: {}", e))
|
||||
}
|
||||
|
||||
/// Преобразовать Lua значение в JSON
|
||||
fn lua_value_to_json(value: LuaValue) -> Result<Value, String> {
|
||||
match value {
|
||||
LuaValue::Nil => Ok(Value::Null),
|
||||
LuaValue::Boolean(b) => Ok(Value::Bool(b)),
|
||||
LuaValue::Integer(i) => Ok(Value::Number(i.into())),
|
||||
LuaValue::Number(n) => {
|
||||
// Попробуем преобразовать в integer если возможно
|
||||
if n.fract() == 0.0 {
|
||||
Ok(Value::Number((n as i64).into()))
|
||||
} else {
|
||||
serde_json::Number::from_f64(n)
|
||||
.map(Value::Number)
|
||||
.ok_or_else(|| "Invalid number".to_string())
|
||||
}
|
||||
}
|
||||
LuaValue::String(s) => Ok(Value::String(s.to_string_lossy().to_string())),
|
||||
LuaValue::Table(table) => {
|
||||
let mut map = serde_json::Map::new();
|
||||
|
||||
for pair in table.pairs::<LuaValue, LuaValue>() {
|
||||
match pair {
|
||||
Ok((key, value)) => {
|
||||
let key_str = match key {
|
||||
LuaValue::String(s) => s.to_string_lossy().to_string(),
|
||||
LuaValue::Integer(i) => i.to_string(),
|
||||
LuaValue::Number(n) => n.to_string(),
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
let value_json = Self::lua_value_to_json(value)?;
|
||||
map.insert(key_str, value_json);
|
||||
}
|
||||
Err(e) => return Err(format!("Failed to parse table pair: {}", e)),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Value::Object(map))
|
||||
}
|
||||
_ => Err(format!("Unsupported Lua type: {:?}", value.type_name())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Преобразовать JSON в Lua значение
|
||||
fn json_to_lua_value(lua: &Lua, value: Value) -> LuaResult<LuaValue> {
|
||||
match value {
|
||||
Value::Null => Ok(LuaValue::Nil),
|
||||
Value::Bool(b) => Ok(LuaValue::Boolean(b)),
|
||||
Value::Number(n) => {
|
||||
if let Some(i) = n.as_i64() {
|
||||
Ok(LuaValue::Integer(i))
|
||||
} else if let Some(f) = n.as_f64() {
|
||||
Ok(LuaValue::Number(f))
|
||||
} else {
|
||||
Err(LuaError::external("Invalid number"))
|
||||
}
|
||||
}
|
||||
Value::String(s) => Ok(LuaValue::String(lua.create_string(&s)?)),
|
||||
Value::Array(arr) => {
|
||||
let table = lua.create_table()?;
|
||||
for (i, item) in arr.into_iter().enumerate() {
|
||||
let lua_value = Self::json_to_lua_value(lua, item)?;
|
||||
table.set(i + 1, lua_value)?;
|
||||
}
|
||||
Ok(LuaValue::Table(table))
|
||||
}
|
||||
Value::Object(obj) => {
|
||||
let table = lua.create_table()?;
|
||||
for (key, value) in obj {
|
||||
let lua_value = Self::json_to_lua_value(lua, value)?;
|
||||
table.set(key, lua_value)?;
|
||||
}
|
||||
Ok(LuaValue::Table(table))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user