diff --git a/app/MindWork AI Studio/Dialogs/DataSourceERI_V1Dialog.razor.cs b/app/MindWork AI Studio/Dialogs/DataSourceERI_V1Dialog.razor.cs
index 4ee8bb1a..8bec772a 100644
--- a/app/MindWork AI Studio/Dialogs/DataSourceERI_V1Dialog.razor.cs
+++ b/app/MindWork AI Studio/Dialogs/DataSourceERI_V1Dialog.razor.cs
@@ -116,7 +116,7 @@ public partial class DataSourceERI_V1Dialog : MSGComponentBase, ISecretId
if (this.dataAuthMethod is AuthMethod.TOKEN or AuthMethod.USERNAME_PASSWORD)
{
// Load the secret:
- var requestedSecret = await this.RustService.GetSecret(this);
+ var requestedSecret = await this.RustService.GetSecret(this, SecretStoreType.DATA_SOURCE);
if (requestedSecret.Success)
this.dataSecret = await requestedSecret.Secret.Decrypt(this.encryption);
else
@@ -324,7 +324,7 @@ public partial class DataSourceERI_V1Dialog : MSGComponentBase, ISecretId
if (!string.IsNullOrWhiteSpace(this.dataSecret))
{
// Store the secret in the OS secure storage:
- var storeResponse = await this.RustService.SetSecret(this, this.dataSecret);
+ var storeResponse = await this.RustService.SetSecret(this, this.dataSecret, SecretStoreType.DATA_SOURCE);
if (!storeResponse.Success)
{
this.dataSecretStorageIssue = string.Format(T("Failed to store the auth. secret in the operating system. The message was: {0}. Please try again."), storeResponse.Issue);
diff --git a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogDataSources.razor.cs b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogDataSources.razor.cs
index e8792b1a..f3e89e75 100644
--- a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogDataSources.razor.cs
+++ b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogDataSources.razor.cs
@@ -180,7 +180,7 @@ public partial class SettingsDialogDataSources : SettingsDialogBase
// All other auth methods require a secret, which we need to delete now:
else
{
- var deleteSecretResponse = await this.RustService.DeleteSecret(externalDataSource);
+ var deleteSecretResponse = await this.RustService.DeleteSecret(externalDataSource, SecretStoreType.DATA_SOURCE);
if (deleteSecretResponse.Success)
applyChanges = true;
}
diff --git a/app/MindWork AI Studio/Settings/DataModel/DataSourceERI_V1.cs b/app/MindWork AI Studio/Settings/DataModel/DataSourceERI_V1.cs
index 89b2cadd..0eef7262 100644
--- a/app/MindWork AI Studio/Settings/DataModel/DataSourceERI_V1.cs
+++ b/app/MindWork AI Studio/Settings/DataModel/DataSourceERI_V1.cs
@@ -2,7 +2,6 @@
using AIStudio.Assistants.ERI;
using AIStudio.Chat;
-using AIStudio.Tools;
using AIStudio.Tools.ERIClient;
using AIStudio.Tools.ERIClient.DataModel;
using AIStudio.Tools.PluginSystem;
@@ -313,7 +312,8 @@ public readonly record struct DataSourceERI_V1 : IERIDataSource
PendingEnterpriseSecrets.Add(new(
$"{ISecretId.ENTERPRISE_KEY_PREFIX}::{dataSource.Id}",
dataSource.Name,
- decryptedSecret));
+ decryptedSecret,
+ SecretStoreType.DATA_SOURCE));
LOGGER.LogDebug($"Successfully decrypted the {secretFieldName} for data source {idx}. It will be stored in the OS keyring. (Plugin ID: {configPluginId})");
return true;
}
diff --git a/app/MindWork AI Studio/Settings/IDataSource.cs b/app/MindWork AI Studio/Settings/IDataSource.cs
index 39291ad2..7e29123d 100644
--- a/app/MindWork AI Studio/Settings/IDataSource.cs
+++ b/app/MindWork AI Studio/Settings/IDataSource.cs
@@ -16,21 +16,6 @@ namespace AIStudio.Settings;
[JsonDerivedType(typeof(DataSourceERI_V1), nameof(DataSourceType.ERI_V1))]
public interface IDataSource : IConfigurationObject
{
- ///
- /// The number of the data source.
- ///
- public uint Num { get; init; }
-
- ///
- /// The unique identifier of the data source.
- ///
- public string Id { get; init; }
-
- ///
- /// The name of the data source.
- ///
- public string Name { get; init; }
-
///
/// Which type of data source is this?
///
@@ -40,16 +25,6 @@ public interface IDataSource : IConfigurationObject
/// Which data security policy is applied to this data source?
///
public DataSourceSecurity SecurityPolicy { get; init; }
-
- ///
- /// Is this data source an enterprise configuration?
- ///
- public bool IsEnterpriseConfiguration { get; init; }
-
- ///
- /// The ID of the enterprise configuration plugin.
- ///
- public Guid EnterpriseConfigurationPluginId { get; init; }
///
/// The maximum number of matches to return when retrieving data from the ERI server.
diff --git a/app/MindWork AI Studio/Settings/IERIDataSource.cs b/app/MindWork AI Studio/Settings/IERIDataSource.cs
index 5744ace8..40dd625d 100644
--- a/app/MindWork AI Studio/Settings/IERIDataSource.cs
+++ b/app/MindWork AI Studio/Settings/IERIDataSource.cs
@@ -1,4 +1,5 @@
using AIStudio.Assistants.ERI;
+using AIStudio.Settings.DataModel;
using AIStudio.Tools.ERIClient.DataModel;
namespace AIStudio.Settings;
diff --git a/app/MindWork AI Studio/Settings/IExternalDataSource.cs b/app/MindWork AI Studio/Settings/IExternalDataSource.cs
index 8dd03718..6b75fa56 100644
--- a/app/MindWork AI Studio/Settings/IExternalDataSource.cs
+++ b/app/MindWork AI Studio/Settings/IExternalDataSource.cs
@@ -7,7 +7,7 @@ public interface IExternalDataSource : IDataSource, ISecretId
#region Implementation of ISecretId
[JsonIgnore]
- string ISecretId.SecretId => this.IsEnterpriseConfiguration ? $"{ISecretId.ENTERPRISE_KEY_PREFIX}::{this.Id}" : this.Id;
+ string ISecretId.SecretId => this.IsEnterpriseConfiguration ? $"{ENTERPRISE_KEY_PREFIX}::{this.Id}" : this.Id;
[JsonIgnore]
string ISecretId.SecretName => this.Name;
diff --git a/app/MindWork AI Studio/Tools/ERIClient/ERIClientV1.cs b/app/MindWork AI Studio/Tools/ERIClient/ERIClientV1.cs
index 287be619..f00976b9 100644
--- a/app/MindWork AI Studio/Tools/ERIClient/ERIClientV1.cs
+++ b/app/MindWork AI Studio/Tools/ERIClient/ERIClientV1.cs
@@ -119,7 +119,7 @@ public class ERIClientV1(IERIDataSource dataSource) : ERIClientBase(dataSource),
string password;
if (string.IsNullOrWhiteSpace(temporarySecret))
{
- var passwordResponse = await rustService.GetSecret(this.DataSource);
+ var passwordResponse = await rustService.GetSecret(this.DataSource, SecretStoreType.DATA_SOURCE);
if (!passwordResponse.Success)
{
return new()
@@ -173,7 +173,7 @@ public class ERIClientV1(IERIDataSource dataSource) : ERIClientBase(dataSource),
string token;
if (string.IsNullOrWhiteSpace(temporarySecret))
{
- var tokenResponse = await rustService.GetSecret(this.DataSource);
+ var tokenResponse = await rustService.GetSecret(this.DataSource, SecretStoreType.DATA_SOURCE);
if (!tokenResponse.Success)
{
return new()
diff --git a/app/MindWork AI Studio/Tools/PluginSystem/PendingEnterpriseApiKey.cs b/app/MindWork AI Studio/Tools/PluginSystem/PendingEnterpriseApiKey.cs
index 91d8ec04..63b7ebfb 100644
--- a/app/MindWork AI Studio/Tools/PluginSystem/PendingEnterpriseApiKey.cs
+++ b/app/MindWork AI Studio/Tools/PluginSystem/PendingEnterpriseApiKey.cs
@@ -13,81 +13,4 @@ public sealed record PendingEnterpriseApiKey(
string SecretId,
string SecretName,
string ApiKey,
- SecretStoreType StoreType);
-
-///
-/// Static container for pending API keys during plugin loading.
-///
-public static class PendingEnterpriseApiKeys
-{
- private static readonly List PENDING_KEYS = [];
- private static readonly Lock LOCK = new();
-
- ///
- /// Adds a pending API key to the list.
- ///
- /// The pending API key to add.
- public static void Add(PendingEnterpriseApiKey key)
- {
- lock (LOCK)
- PENDING_KEYS.Add(key);
- }
-
- ///
- /// Gets and clears all pending API keys.
- ///
- /// A list of all pending API keys.
- public static IReadOnlyList GetAndClear()
- {
- lock (LOCK)
- {
- var keys = PENDING_KEYS.ToList();
- PENDING_KEYS.Clear();
- return keys;
- }
- }
-}
-
-///
-/// Represents a pending enterprise secret that needs to be stored in the OS keyring.
-///
-/// The secret ID.
-/// The secret name.
-/// The decrypted secret data.
-public sealed record PendingEnterpriseSecret(
- string SecretId,
- string SecretName,
- string SecretData);
-
-///
-/// Static container for pending enterprise secrets during plugin loading.
-///
-public static class PendingEnterpriseSecrets
-{
- private static readonly List PENDING_SECRETS = [];
- private static readonly Lock LOCK = new();
-
- ///
- /// Adds a pending enterprise secret to the list.
- ///
- /// The pending enterprise secret to add.
- public static void Add(PendingEnterpriseSecret secret)
- {
- lock (LOCK)
- PENDING_SECRETS.Add(secret);
- }
-
- ///
- /// Gets and clears all pending enterprise secrets.
- ///
- /// A list of all pending enterprise secrets.
- public static IReadOnlyList GetAndClear()
- {
- lock (LOCK)
- {
- var secrets = PENDING_SECRETS.ToList();
- PENDING_SECRETS.Clear();
- return secrets;
- }
- }
-}
\ No newline at end of file
+ SecretStoreType StoreType);
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/PluginSystem/PendingEnterpriseApiKeys.cs b/app/MindWork AI Studio/Tools/PluginSystem/PendingEnterpriseApiKeys.cs
new file mode 100644
index 00000000..8824424e
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/PluginSystem/PendingEnterpriseApiKeys.cs
@@ -0,0 +1,34 @@
+namespace AIStudio.Tools.PluginSystem;
+
+///
+/// Static container for pending API keys during plugin loading.
+///
+public static class PendingEnterpriseApiKeys
+{
+ private static readonly List PENDING_KEYS = [];
+ private static readonly Lock LOCK = new();
+
+ ///
+ /// Adds a pending API key to the list.
+ ///
+ /// The pending API key to add.
+ public static void Add(PendingEnterpriseApiKey key)
+ {
+ lock (LOCK)
+ PENDING_KEYS.Add(key);
+ }
+
+ ///
+ /// Gets and clears all pending API keys.
+ ///
+ /// A list of all pending API keys.
+ public static IReadOnlyList GetAndClear()
+ {
+ lock (LOCK)
+ {
+ var keys = PENDING_KEYS.ToList();
+ PENDING_KEYS.Clear();
+ return keys;
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/PluginSystem/PendingEnterpriseSecret.cs b/app/MindWork AI Studio/Tools/PluginSystem/PendingEnterpriseSecret.cs
new file mode 100644
index 00000000..d4be88e4
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/PluginSystem/PendingEnterpriseSecret.cs
@@ -0,0 +1,14 @@
+namespace AIStudio.Tools.PluginSystem;
+
+///
+/// Represents a pending enterprise secret that needs to be stored in the OS keyring.
+///
+/// The secret ID.
+/// The secret name.
+/// The decrypted secret data.
+/// The type of secret store to use.
+public sealed record PendingEnterpriseSecret(
+ string SecretId,
+ string SecretName,
+ string SecretData,
+ SecretStoreType StoreType);
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/PluginSystem/PendingEnterpriseSecrets.cs b/app/MindWork AI Studio/Tools/PluginSystem/PendingEnterpriseSecrets.cs
new file mode 100644
index 00000000..1fef45fa
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/PluginSystem/PendingEnterpriseSecrets.cs
@@ -0,0 +1,34 @@
+namespace AIStudio.Tools.PluginSystem;
+
+///
+/// Static container for pending enterprise secrets during plugin loading.
+///
+public static class PendingEnterpriseSecrets
+{
+ private static readonly List PENDING_SECRETS = [];
+ private static readonly Lock LOCK = new();
+
+ ///
+ /// Adds a pending enterprise secret to the list.
+ ///
+ /// The pending enterprise secret to add.
+ public static void Add(PendingEnterpriseSecret secret)
+ {
+ lock (LOCK)
+ PENDING_SECRETS.Add(secret);
+ }
+
+ ///
+ /// Gets and clears all pending enterprise secrets.
+ ///
+ /// A list of all pending enterprise secrets.
+ public static IReadOnlyList GetAndClear()
+ {
+ lock (LOCK)
+ {
+ var secrets = PENDING_SECRETS.ToList();
+ PENDING_SECRETS.Clear();
+ return secrets;
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/PluginSystem/PluginConfiguration.cs b/app/MindWork AI Studio/Tools/PluginSystem/PluginConfiguration.cs
index f5b09f1f..77391601 100644
--- a/app/MindWork AI Studio/Tools/PluginSystem/PluginConfiguration.cs
+++ b/app/MindWork AI Studio/Tools/PluginSystem/PluginConfiguration.cs
@@ -62,7 +62,7 @@ public sealed class PluginConfiguration(bool isInternal, LuaState state, PluginT
try
{
var secretId = new TemporarySecretId(pendingSecret.SecretId, pendingSecret.SecretName);
- var result = await rustService.SetSecret(secretId, pendingSecret.SecretData);
+ var result = await rustService.SetSecret(secretId, pendingSecret.SecretData, pendingSecret.StoreType);
if (result.Success)
LOG.LogDebug($"Successfully stored enterprise secret for '{pendingSecret.SecretName}' in the OS keyring.");
diff --git a/app/MindWork AI Studio/Tools/PluginSystem/PluginConfigurationObject.cs b/app/MindWork AI Studio/Tools/PluginSystem/PluginConfigurationObject.cs
index 8bd7ae0c..26f10e7d 100644
--- a/app/MindWork AI Studio/Tools/PluginSystem/PluginConfigurationObject.cs
+++ b/app/MindWork AI Studio/Tools/PluginSystem/PluginConfigurationObject.cs
@@ -252,6 +252,7 @@ public sealed record PluginConfigurationObject
/// A list of currently available plugins.
/// A list of all existing configuration objects.
/// An optional parameter specifying the type of secret store to use for deleting associated API keys from the OS keyring, if applicable.
+ /// When true, delete the associated non-API-key secret from the OS keyring.
/// Returns true if the configuration was altered during cleanup; otherwise, false.
public static async Task CleanLeftOverConfigurationObjects(
PluginConfigurationObjectType configObjectType,
@@ -304,7 +305,7 @@ public sealed record PluginConfigurationObject
// Delete the API key from the OS keyring if the removed object has one:
if(deleteSecret && item is ISecretId regularSecretId)
{
- var deleteResult = await RUST_SERVICE.DeleteSecret(regularSecretId);
+ var deleteResult = await RUST_SERVICE.DeleteSecret(regularSecretId, secretStoreType ?? SecretStoreType.DATA_SOURCE);
if (deleteResult.Success)
LOG.LogInformation($"Successfully deleted secret for removed enterprise object '{item.Name}' from the OS keyring.");
else
diff --git a/app/MindWork AI Studio/Tools/PluginSystem/PluginFactory.Loading.cs b/app/MindWork AI Studio/Tools/PluginSystem/PluginFactory.Loading.cs
index 0b7147da..d09eaf34 100644
--- a/app/MindWork AI Studio/Tools/PluginSystem/PluginFactory.Loading.cs
+++ b/app/MindWork AI Studio/Tools/PluginSystem/PluginFactory.Loading.cs
@@ -175,7 +175,7 @@ public static partial class PluginFactory
wasConfigurationChanged = true;
// Check data sources:
- if(await PluginConfigurationObject.CleanLeftOverConfigurationObjects(PluginConfigurationObjectType.DATA_SOURCE, x => x.DataSources, AVAILABLE_PLUGINS, configObjectList, deleteSecret: true))
+ if(await PluginConfigurationObject.CleanLeftOverConfigurationObjects(PluginConfigurationObjectType.DATA_SOURCE, x => x.DataSources, AVAILABLE_PLUGINS, configObjectList, SecretStoreType.DATA_SOURCE, deleteSecret: true))
wasConfigurationChanged = true;
// Check chat templates:
diff --git a/app/MindWork AI Studio/Tools/SecretStoreType.cs b/app/MindWork AI Studio/Tools/SecretStoreType.cs
index 9ebcadcd..5e9182d7 100644
--- a/app/MindWork AI Studio/Tools/SecretStoreType.cs
+++ b/app/MindWork AI Studio/Tools/SecretStoreType.cs
@@ -1,10 +1,10 @@
namespace AIStudio.Tools;
///
-/// Represents the type of secret store used for API keys.
+/// Represents the type of secret store used for API keys and other secrets.
///
///
-/// Different provider types use different prefixes for storing API keys.
+/// Different provider and secret types use different prefixes for storing secrets.
/// This prevents collisions when the same instance name is used across
/// different provider types (e.g., LLM, Embedding, Transcription).
///
@@ -29,4 +29,9 @@ public enum SecretStoreType
/// Image provider secrets. Uses the "image::" prefix.
///
IMAGE_PROVIDER,
+
+ ///
+ /// Data source secrets. Uses the "data-source::" prefix.
+ ///
+ DATA_SOURCE,
}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/SecretStoreTypeExtensions.cs b/app/MindWork AI Studio/Tools/SecretStoreTypeExtensions.cs
index d0d4ba9e..5e8ae2f0 100644
--- a/app/MindWork AI Studio/Tools/SecretStoreTypeExtensions.cs
+++ b/app/MindWork AI Studio/Tools/SecretStoreTypeExtensions.cs
@@ -9,12 +9,14 @@ public static class SecretStoreTypeExtensions
/// LLM_PROVIDER uses the legacy "provider" prefix for backward compatibility.
///
/// The SecretStoreType enum value.
- /// >The corresponding prefix string.
+ /// The corresponding prefix string.
public static string Prefix(this SecretStoreType type) => type switch
{
SecretStoreType.LLM_PROVIDER => "provider",
SecretStoreType.EMBEDDING_PROVIDER => "embedding",
SecretStoreType.TRANSCRIPTION_PROVIDER => "transcription",
+ SecretStoreType.IMAGE_PROVIDER => "image",
+ SecretStoreType.DATA_SOURCE => "data-source",
_ => "provider",
};
diff --git a/app/MindWork AI Studio/Tools/Services/EnterpriseEnvironmentService.cs b/app/MindWork AI Studio/Tools/Services/EnterpriseEnvironmentService.cs
index cd564e9a..6db55a6c 100644
--- a/app/MindWork AI Studio/Tools/Services/EnterpriseEnvironmentService.cs
+++ b/app/MindWork AI Studio/Tools/Services/EnterpriseEnvironmentService.cs
@@ -200,7 +200,7 @@ public sealed class EnterpriseEnvironmentService(ILogger(), null, secretTargets);
+ AddEnterpriseManagedSecretTargets(configurationData.DataSources.OfType(), SecretStoreType.DATA_SOURCE, secretTargets);
return secretTargets.ToList();
}
private static void AddEnterpriseManagedSecretTargets(
IEnumerable secrets,
- SecretStoreType? storeType,
+ SecretStoreType storeType,
ISet secretTargets) where TSecret : ISecretId, IConfigurationObject
{
foreach (var secret in secrets)
diff --git a/app/MindWork AI Studio/Tools/Services/RustService.Secrets.cs b/app/MindWork AI Studio/Tools/Services/RustService.Secrets.cs
index 49f51a1d..f66801a6 100644
--- a/app/MindWork AI Studio/Tools/Services/RustService.Secrets.cs
+++ b/app/MindWork AI Studio/Tools/Services/RustService.Secrets.cs
@@ -4,26 +4,42 @@ namespace AIStudio.Tools.Services;
public sealed partial class RustService
{
+ private static string SecretKey(ISecretId secretId, SecretStoreType storeType) => $"{storeType.Prefix()}::{secretId.SecretId}::{secretId.SecretName}";
+
+ private static string LegacySecretKey(ISecretId secretId) => $"secret::{secretId.SecretId}::{secretId.SecretName}";
+
///
/// Try to get the secret data for the given secret ID.
///
/// The secret ID to get the data for.
+ /// The secret store type.
/// Indicates if we are trying to get the data. In that case, we don't log errors.
/// The requested secret.
- public async Task GetSecret(ISecretId secretId, bool isTrying = false)
+ public async Task GetSecret(ISecretId secretId, SecretStoreType storeType, bool isTrying = false)
{
- var secretRequest = new SelectSecretRequest($"secret::{secretId.SecretId}::{secretId.SecretName}", Environment.UserName, isTrying);
+ var secretKey = SecretKey(secretId, storeType);
+ var secretRequest = new SelectSecretRequest(secretKey, Environment.UserName, isTrying);
var result = await this.http.PostAsJsonAsync("/secrets/get", secretRequest, this.jsonRustSerializerOptions);
if (!result.IsSuccessStatusCode)
{
if(!isTrying)
- this.logger!.LogError($"Failed to get the secret data for secret ID '{secretId.SecretId}' due to an API issue: '{result.StatusCode}'");
+ this.logger!.LogError($"Failed to get the secret data for '{secretKey}' due to an API issue: '{result.StatusCode}'");
return new RequestedSecret(false, new EncryptedText(string.Empty), TB("Failed to get the secret data due to an API issue."));
}
var secret = await result.Content.ReadFromJsonAsync(this.jsonRustSerializerOptions);
+ if (!secret.Success && storeType is SecretStoreType.DATA_SOURCE)
+ {
+ var legacySecret = await this.GetLegacySecret(secretId, isTrying: true);
+ if (legacySecret.Success)
+ {
+ this.logger!.LogDebug($"Successfully retrieved the legacy data source secret for '{LegacySecretKey(secretId)}'.");
+ return legacySecret;
+ }
+ }
+
if (!secret.Success && !isTrying)
- this.logger!.LogError($"Failed to get the secret data for secret ID '{secretId.SecretId}': '{secret.Issue}'");
+ this.logger!.LogError($"Failed to get the secret data for '{secretKey}': '{secret.Issue}'");
return secret;
}
@@ -33,21 +49,26 @@ public sealed partial class RustService
///
/// The secret ID to store the data for.
/// The data to store.
+ /// The secret store type.
/// The store secret response.
- public async Task SetSecret(ISecretId secretId, string secretData)
+ public async Task SetSecret(ISecretId secretId, string secretData, SecretStoreType storeType)
{
+ var secretKey = SecretKey(secretId, storeType);
var encryptedSecret = await this.encryptor!.Encrypt(secretData);
- var request = new StoreSecretRequest($"secret::{secretId.SecretId}::{secretId.SecretName}", Environment.UserName, encryptedSecret);
+ var request = new StoreSecretRequest(secretKey, Environment.UserName, encryptedSecret);
var result = await this.http.PostAsJsonAsync("/secrets/store", request, this.jsonRustSerializerOptions);
if (!result.IsSuccessStatusCode)
{
- this.logger!.LogError($"Failed to store the secret data for secret ID '{secretId.SecretId}' due to an API issue: '{result.StatusCode}'");
- return new StoreSecretResponse(false, TB("Failed to get the secret data due to an API issue."));
+ this.logger!.LogError($"Failed to store the secret data for '{secretKey}' due to an API issue: '{result.StatusCode}'");
+ return new StoreSecretResponse(false, TB("Failed to store the secret data due to an API issue."));
}
var state = await result.Content.ReadFromJsonAsync(this.jsonRustSerializerOptions);
if (!state.Success)
- this.logger!.LogError($"Failed to store the secret data for secret ID '{secretId.SecretId}': '{state.Issue}'");
+ this.logger!.LogError($"Failed to store the secret data for '{secretKey}': '{state.Issue}'");
+
+ if (state.Success && storeType is SecretStoreType.DATA_SOURCE)
+ await this.DeleteSecretKey(secretId, LegacySecretKey(secretId));
return state;
}
@@ -56,20 +77,49 @@ public sealed partial class RustService
/// Tries to delete the secret data for the given secret ID.
///
/// The secret ID to delete the data for.
+ /// The secret store type.
/// The delete secret response.
- public async Task DeleteSecret(ISecretId secretId)
+ public async Task DeleteSecret(ISecretId secretId, SecretStoreType storeType)
{
- var request = new SelectSecretRequest($"secret::{secretId.SecretId}::{secretId.SecretName}", Environment.UserName, false);
+ var deleteResult = await this.DeleteSecretKey(secretId, SecretKey(secretId, storeType));
+ if (storeType is not SecretStoreType.DATA_SOURCE || !deleteResult.Success)
+ return deleteResult;
+
+ var legacyDeleteResult = await this.DeleteSecretKey(secretId, LegacySecretKey(secretId));
+ if (!legacyDeleteResult.Success)
+ return legacyDeleteResult;
+
+ return deleteResult with { WasEntryFound = deleteResult.WasEntryFound || legacyDeleteResult.WasEntryFound };
+ }
+
+ private async Task GetLegacySecret(ISecretId secretId, bool isTrying)
+ {
+ var secretKey = LegacySecretKey(secretId);
+ var secretRequest = new SelectSecretRequest(secretKey, Environment.UserName, isTrying);
+ var result = await this.http.PostAsJsonAsync("/secrets/get", secretRequest, this.jsonRustSerializerOptions);
+ if (!result.IsSuccessStatusCode)
+ {
+ if(!isTrying)
+ this.logger!.LogError($"Failed to get the secret data for '{secretKey}' due to an API issue: '{result.StatusCode}'");
+ return new RequestedSecret(false, new EncryptedText(string.Empty), TB("Failed to get the secret data due to an API issue."));
+ }
+
+ return await result.Content.ReadFromJsonAsync(this.jsonRustSerializerOptions);
+ }
+
+ private async Task DeleteSecretKey(ISecretId secretId, string secretKey)
+ {
+ var request = new SelectSecretRequest(secretKey, Environment.UserName, false);
var result = await this.http.PostAsJsonAsync("/secrets/delete", request, this.jsonRustSerializerOptions);
if (!result.IsSuccessStatusCode)
{
- this.logger!.LogError($"Failed to delete the secret data for secret ID '{secretId.SecretId}' due to an API issue: '{result.StatusCode}'");
+ this.logger!.LogError($"Failed to delete the secret data for '{secretKey}' due to an API issue: '{result.StatusCode}'");
return new DeleteSecretResponse{Success = false, WasEntryFound = false, Issue = TB("Failed to delete the secret data due to an API issue.")};
}
var state = await result.Content.ReadFromJsonAsync(this.jsonRustSerializerOptions);
if (!state.Success)
- this.logger!.LogError($"Failed to delete the secret data for secret ID '{secretId.SecretId}': '{state.Issue}'");
+ this.logger!.LogError($"Failed to delete the secret data for '{secretKey}': '{state.Issue}'");
return state;
}