mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-08-18 02:12:12 +00:00
Fixed loading Lua modules of a plugin during its validation
This commit is contained in:
parent
f0c35d8914
commit
4a8190240e
@ -385,16 +385,24 @@ public static partial class PluginFactory
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<PluginBase> Load(string? pluginPath, string code, CancellationToken cancellationToken = default)
|
||||
/// <param name="pluginPath">The directory the plugin is located in, or null when the code has no directory yet.</param>
|
||||
/// <param name="code">The Lua code of the plugin's main file.</param>
|
||||
/// <param name="cancellationToken">Cancellation token for running the Lua code.</param>
|
||||
/// <param name="allowedBaseDirectory">
|
||||
/// The directory the plugin path must be nested in. Without it, the installed plugins directory
|
||||
/// is used. Validating a plugin before its installation needs this, because the plugin lives in
|
||||
/// a staging directory at that point and could not load any of its own Lua modules otherwise.
|
||||
/// </param>
|
||||
public static async Task<PluginBase> Load(string? pluginPath, string code, CancellationToken cancellationToken = default, string? allowedBaseDirectory = null)
|
||||
{
|
||||
if(ForbiddenPlugins.Check(code) is { IsForbidden: true } forbiddenState)
|
||||
return new NoPlugin($"This plugin is forbidden: {forbiddenState.Message}");
|
||||
|
||||
|
||||
var state = LuaState.Create();
|
||||
if (!string.IsNullOrWhiteSpace(pluginPath))
|
||||
{
|
||||
// Add the module loader so that the plugin can load other Lua modules:
|
||||
state.ModuleLoader = new PluginLoader(pluginPath);
|
||||
state.ModuleLoader = new PluginLoader(pluginPath, allowedBaseDirectory);
|
||||
}
|
||||
|
||||
// Add some useful libraries:
|
||||
|
||||
@ -14,10 +14,17 @@ namespace AIStudio.Tools.PluginSystem;
|
||||
/// Loading other modules outside the plugin directory is not allowed.
|
||||
/// </remarks>
|
||||
/// <param name="pluginDirectory">The directory where the plugin is located.</param>
|
||||
public sealed class PluginLoader(string pluginDirectory) : ILuaModuleLoader
|
||||
/// <param name="allowedBaseDirectory">
|
||||
/// The directory the plugin directory must be nested in. Without it, the installed plugins directory
|
||||
/// is used. Validating a plugin before its installation needs this, because the plugin is not
|
||||
/// installed yet and lives in a staging directory outside the installed plugins directory.
|
||||
/// </param>
|
||||
public sealed class PluginLoader(string pluginDirectory, string? allowedBaseDirectory = null) : ILuaModuleLoader
|
||||
{
|
||||
private static readonly string PLUGIN_BASE_PATH = Path.Join(SettingsManager.DataDirectory, "plugins");
|
||||
|
||||
private readonly string baseDirectory = string.IsNullOrWhiteSpace(allowedBaseDirectory) ? PLUGIN_BASE_PATH : allowedBaseDirectory;
|
||||
|
||||
#region Implementation of ILuaModuleLoader
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -26,11 +33,11 @@ public sealed class PluginLoader(string pluginDirectory) : ILuaModuleLoader
|
||||
// Ensure that the user doesn't try to escape the plugin directory:
|
||||
if (moduleName.Contains("..") || pluginDirectory.Contains(".."))
|
||||
return false;
|
||||
|
||||
// Ensure that the plugin directory is nested in the plugin base path:
|
||||
if (!pluginDirectory.StartsWith(PLUGIN_BASE_PATH, StringComparison.OrdinalIgnoreCase))
|
||||
|
||||
// Ensure that the plugin directory is nested in the allowed base directory:
|
||||
if (!pluginDirectory.StartsWith(this.baseDirectory, StringComparison.OrdinalIgnoreCase))
|
||||
return false;
|
||||
|
||||
|
||||
var path = Path.Join(pluginDirectory, $"{moduleName}.lua");
|
||||
return File.Exists(path);
|
||||
}
|
||||
@ -40,7 +47,7 @@ public sealed class PluginLoader(string pluginDirectory) : ILuaModuleLoader
|
||||
{
|
||||
var path = Path.Join(pluginDirectory, $"{moduleName}.lua");
|
||||
var code = await File.ReadAllTextAsync(path, Encoding.UTF8, cancellationToken);
|
||||
|
||||
|
||||
return new(moduleName, code);
|
||||
}
|
||||
|
||||
|
||||
@ -572,7 +572,10 @@ public sealed class AssistantPluginInstallService
|
||||
private static async Task<AssistantPluginValidationResult> ValidateAssistantPluginCodeAsync(string pluginDirectory, string pluginCode,
|
||||
string notAssistantIssue, string invalidAssistantIssue, string internalPluginIdIssue, CancellationToken token)
|
||||
{
|
||||
var plugin = await PluginFactory.Load(pluginDirectory, pluginCode, token);
|
||||
// The plugin is not installed yet: it sits in a staging directory outside the installed
|
||||
// plugins directory. We allow that directory as the module base, so the plugin can load its
|
||||
// own Lua modules, e.g., an icon.lua, while we validate it:
|
||||
var plugin = await PluginFactory.Load(pluginDirectory, pluginCode, token, pluginDirectory);
|
||||
if (plugin is not PluginAssistants assistantPlugin)
|
||||
return AssistantPluginValidationResult.Failure(string.Format(notAssistantIssue, string.Join("; ", plugin.Issues)));
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user