mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-08-11 22:12:11 +00:00
Fixed enterprise configuration plugins losing to local plugins with the same ID
This commit is contained in:
parent
d1a6781ea6
commit
357eadd12d
@ -110,10 +110,26 @@ public static partial class PluginFactory
|
||||
|
||||
LOG.LogInformation($"Successfully loaded plugin: '{pluginMainFile}' (Id='{plugin.Id}', Type='{plugin.Type}', Name='{plugin.Name}', Version='{plugin.Version}', Authors='{string.Join(", ", plugin.Authors)}')");
|
||||
|
||||
var isConfigurationPluginInConfigDirectory =
|
||||
plugin.Type is PluginType.CONFIGURATION &&
|
||||
pluginPath.StartsWith(CONFIGURATION_PLUGINS_ROOT, StringComparison.OrdinalIgnoreCase);
|
||||
//
|
||||
// Plugin IDs must be unique: many lookups resolve a plugin by its ID alone, e.g.
|
||||
// the base language plugin in PluginFactory.Starting or the owner of a locked
|
||||
// setting. When two plugins share an ID, the one deployed by the organization's
|
||||
// IT wins. Otherwise, a manually placed copy could outrank the enterprise
|
||||
// configuration, which is the exact opposite of what an organization expects:
|
||||
//
|
||||
if (AVAILABLE_PLUGINS.FirstOrDefault(candidate => candidate.Id == plugin.Id) is { } duplicatePlugin)
|
||||
{
|
||||
if (!IsEnterpriseConfigurationPath(pluginPath) || IsEnterpriseConfigurationPath(duplicatePlugin.LocalPath))
|
||||
{
|
||||
LOG.LogWarning($"Ignoring the plugin '{pluginMainFile}': its ID ('{plugin.Id}') is already used by the plugin at '{duplicatePlugin.LocalPath}'. Plugin IDs must be unique. Please remove one of these plugins.");
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG.LogWarning($"Ignoring the plugin at '{duplicatePlugin.LocalPath}': it uses the ID ('{plugin.Id}') of the enterprise configuration plugin at '{pluginPath}'. Plugins deployed by your organization's IT take precedence.");
|
||||
AVAILABLE_PLUGINS.Remove(duplicatePlugin);
|
||||
}
|
||||
|
||||
var isConfigurationPluginInConfigDirectory = plugin.Type is PluginType.CONFIGURATION && IsEnterpriseConfigurationPath(pluginPath);
|
||||
var isManagedByConfigServer = false;
|
||||
Guid? managedConfigurationId = null;
|
||||
if (plugin is PluginConfiguration configPlugin)
|
||||
|
||||
@ -76,6 +76,35 @@ public static partial class PluginFactory
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether a plugin directory belongs to the enterprise configuration area.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Only the IT department of an organization deploys plugins there: the config server downloads
|
||||
/// them into a directory named after their configuration ID. We decide by path on purpose. The
|
||||
/// Lua field DEPLOYED_USING_CONFIG_SERVER is self-declared, so any plugin could claim to be
|
||||
/// deployed by an organization.
|
||||
/// </remarks>
|
||||
/// <param name="pluginPath">The directory of the plugin.</param>
|
||||
/// <returns>True when the directory is nested in the enterprise configuration directory.</returns>
|
||||
private static bool IsEnterpriseConfigurationPath(string? pluginPath)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(pluginPath) || string.IsNullOrWhiteSpace(CONFIGURATION_PLUGINS_ROOT))
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
var configurationRoot = Path.GetFullPath(CONFIGURATION_PLUGINS_ROOT).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + Path.DirectorySeparatorChar;
|
||||
var pluginDirectory = Path.GetFullPath(pluginPath).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + Path.DirectorySeparatorChar;
|
||||
return pluginDirectory.StartsWith(configurationRoot, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.LogWarning(e, $"Was not able to check whether the plugin directory '{pluginPath}' belongs to the enterprise configuration directory. Treating it as a local plugin.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task LockHotReloadAsync()
|
||||
{
|
||||
if (!IsInitialized)
|
||||
|
||||
@ -12,4 +12,5 @@
|
||||
- Fixed configuration-managed settings remaining active after their configuration plugin was removed.
|
||||
- Fixed the integrated code editor to keep errors and other issues in plugin code visible in the footer while scrolling.
|
||||
- Fixed the trusted badge so you can now see at a glance which models are trusted. It is shown consistently for self-hosted models and models from trusted providers.
|
||||
- Fixed which plugin wins when two plugins claim the same plugin ID. Previously, it was down to chance, so a manually placed copy could take over from a configuration your IT department deployed. Configurations from your organization now always win, and the ignored plugin is reported in the log.
|
||||
- Upgraded dependencies to their latest versions to improve security and stability.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user