diff --git a/app/MindWork AI Studio/Agents/AgentDataSourceSelection.cs b/app/MindWork AI Studio/Agents/AgentDataSourceSelection.cs index 7435713..6a0f095 100644 --- a/app/MindWork AI Studio/Agents/AgentDataSourceSelection.cs +++ b/app/MindWork AI Studio/Agents/AgentDataSourceSelection.cs @@ -199,7 +199,7 @@ public sealed class AgentDataSourceSelection (ILogger // Call the ERI server to get the server description: // using var eriClient = ERIClientFactory.Get(eriDataSource.Version, eriDataSource)!; - var authResponse = await eriClient.AuthenticateAsync(eriDataSource, rustService, token); + var authResponse = await eriClient.AuthenticateAsync(rustService, cancellationToken: token); if (authResponse.Successful) { var serverDescriptionResponse = await eriClient.GetDataSourceInfoAsync(token); diff --git a/app/MindWork AI Studio/Dialogs/DataSourceERI-V1InfoDialog.razor.cs b/app/MindWork AI Studio/Dialogs/DataSourceERI-V1InfoDialog.razor.cs index af17351..75b76bd 100644 --- a/app/MindWork AI Studio/Dialogs/DataSourceERI-V1InfoDialog.razor.cs +++ b/app/MindWork AI Studio/Dialogs/DataSourceERI-V1InfoDialog.razor.cs @@ -98,7 +98,7 @@ public partial class DataSourceERI_V1InfoDialog : ComponentBase, IAsyncDisposabl return; } - var loginResult = await client.AuthenticateAsync(this.DataSource, this.RustService); + var loginResult = await client.AuthenticateAsync(this.RustService); if (!loginResult.Successful) { this.dataIssues.Add(loginResult.Message); diff --git a/app/MindWork AI Studio/Dialogs/DataSourceERI_V1Dialog.razor.cs b/app/MindWork AI Studio/Dialogs/DataSourceERI_V1Dialog.razor.cs index dd88c1d..81612a8 100644 --- a/app/MindWork AI Studio/Dialogs/DataSourceERI_V1Dialog.razor.cs +++ b/app/MindWork AI Studio/Dialogs/DataSourceERI_V1Dialog.razor.cs @@ -188,14 +188,8 @@ public partial class DataSourceERI_V1Dialog : ComponentBase, ISecretId try { var cts = new CancellationTokenSource(TimeSpan.FromSeconds(14)); - var dataSource = new DataSourceERI_V1 - { - AuthMethod = this.dataAuthMethod, - Hostname = this.dataHostname, - Port = this.dataPort, - }; - - using var client = ERIClientFactory.Get(ERIVersion.V1, dataSource); + this.DataSource = this.CreateDataSource(); + using var client = ERIClientFactory.Get(ERIVersion.V1, this.DataSource); if(client is null) { await this.form.Validate(); @@ -217,7 +211,7 @@ public partial class DataSourceERI_V1Dialog : ComponentBase, ISecretId this.availableAuthMethods = authSchemes.Data!.Select(n => n.AuthMethod).ToList(); - var loginResult = await client.AuthenticateAsync(this.DataSource, this.RustService, cts.Token); + var loginResult = await client.AuthenticateAsync(this.RustService, this.dataSecret, cts.Token); if (!loginResult.Successful) { await this.form.Validate(); diff --git a/app/MindWork AI Studio/Settings/DataModel/DataSourceERI_V1.cs b/app/MindWork AI Studio/Settings/DataModel/DataSourceERI_V1.cs index 305c1f0..cc43a3e 100644 --- a/app/MindWork AI Studio/Settings/DataModel/DataSourceERI_V1.cs +++ b/app/MindWork AI Studio/Settings/DataModel/DataSourceERI_V1.cs @@ -62,7 +62,7 @@ public readonly record struct DataSourceERI_V1 : IERIDataSource var logger = Program.SERVICE_PROVIDER.GetRequiredService>(); using var eriClient = ERIClientFactory.Get(this.Version, this)!; - var authResponse = await eriClient.AuthenticateAsync(this, rustService, token); + var authResponse = await eriClient.AuthenticateAsync(rustService, cancellationToken: token); if (authResponse.Successful) { var retrievalRequest = new RetrievalRequest diff --git a/app/MindWork AI Studio/Tools/ERIClient/ERIClientBase.cs b/app/MindWork AI Studio/Tools/ERIClient/ERIClientBase.cs index 58811b0..5458bed 100644 --- a/app/MindWork AI Studio/Tools/ERIClient/ERIClientBase.cs +++ b/app/MindWork AI Studio/Tools/ERIClient/ERIClientBase.cs @@ -1,10 +1,14 @@ using System.Text.Json; using System.Text.Json.Serialization; +using AIStudio.Settings; + namespace AIStudio.Tools.ERIClient; -public abstract class ERIClientBase(string baseAddress) : IDisposable +public abstract class ERIClientBase(IERIDataSource dataSource) : IDisposable { + protected readonly IERIDataSource dataSource = dataSource; + protected static readonly JsonSerializerOptions JSON_OPTIONS = new() { WriteIndented = true, @@ -21,7 +25,7 @@ public abstract class ERIClientBase(string baseAddress) : IDisposable protected readonly HttpClient httpClient = new() { - BaseAddress = new Uri(baseAddress), + BaseAddress = new Uri($"{dataSource.Hostname}:{dataSource.Port}"), }; protected string securityToken = string.Empty; diff --git a/app/MindWork AI Studio/Tools/ERIClient/ERIClientFactory.cs b/app/MindWork AI Studio/Tools/ERIClient/ERIClientFactory.cs index 2858164..0beb0f6 100644 --- a/app/MindWork AI Studio/Tools/ERIClient/ERIClientFactory.cs +++ b/app/MindWork AI Studio/Tools/ERIClient/ERIClientFactory.cs @@ -7,7 +7,7 @@ public static class ERIClientFactory { public static IERIClient? Get(ERIVersion version, IERIDataSource dataSource) => version switch { - ERIVersion.V1 => new ERIClientV1($"{dataSource.Hostname}:{dataSource.Port}"), + ERIVersion.V1 => new ERIClientV1(dataSource), _ => null }; diff --git a/app/MindWork AI Studio/Tools/ERIClient/ERIClientV1.cs b/app/MindWork AI Studio/Tools/ERIClient/ERIClientV1.cs index c57d927..178849d 100644 --- a/app/MindWork AI Studio/Tools/ERIClient/ERIClientV1.cs +++ b/app/MindWork AI Studio/Tools/ERIClient/ERIClientV1.cs @@ -7,7 +7,7 @@ using AIStudio.Tools.Services; namespace AIStudio.Tools.ERIClient; -public class ERIClientV1(string baseAddress) : ERIClientBase(baseAddress), IERIClient +public class ERIClientV1(IERIDataSource dataSource) : ERIClientBase(dataSource), IERIClient { #region Implementation of IERIClient @@ -59,13 +59,13 @@ public class ERIClientV1(string baseAddress) : ERIClientBase(baseAddress), IERIC } } - public async Task> AuthenticateAsync(IERIDataSource dataSource, RustService rustService, CancellationToken cancellationToken = default) + public async Task> AuthenticateAsync(RustService rustService, string? temporarySecret = null, CancellationToken cancellationToken = default) { try { - var authMethod = dataSource.AuthMethod; - var username = dataSource.Username; - switch (dataSource.AuthMethod) + var authMethod = this.dataSource.AuthMethod; + var username = this.dataSource.Username; + switch (this.dataSource.AuthMethod) { case AuthMethod.NONE: using (var request = new HttpRequestMessage(HttpMethod.Post, $"auth?authMethod={authMethod}")) @@ -99,17 +99,24 @@ public class ERIClientV1(string baseAddress) : ERIClientBase(baseAddress), IERIC } case AuthMethod.USERNAME_PASSWORD: - var passwordResponse = await rustService.GetSecret(dataSource); - if (!passwordResponse.Success) + string password; + if (string.IsNullOrWhiteSpace(temporarySecret)) { - return new() + var passwordResponse = await rustService.GetSecret(this.dataSource); + if (!passwordResponse.Success) { - Successful = false, - Message = "Failed to retrieve the password." - }; - } + return new() + { + Successful = false, + Message = "Failed to retrieve the password." + }; + } + + password = await passwordResponse.Secret.Decrypt(Program.ENCRYPTION); + } + else + password = temporarySecret; - var password = await passwordResponse.Secret.Decrypt(Program.ENCRYPTION); using (var request = new HttpRequestMessage(HttpMethod.Post, $"auth?authMethod={authMethod}")) { // We must send both values inside the header. The username field is named 'user'. @@ -146,17 +153,24 @@ public class ERIClientV1(string baseAddress) : ERIClientBase(baseAddress), IERIC } case AuthMethod.TOKEN: - var tokenResponse = await rustService.GetSecret(dataSource); - if (!tokenResponse.Success) + string token; + if (string.IsNullOrWhiteSpace(temporarySecret)) { - return new() + var tokenResponse = await rustService.GetSecret(this.dataSource); + if (!tokenResponse.Success) { - Successful = false, - Message = "Failed to retrieve the access token." - }; - } + return new() + { + Successful = false, + Message = "Failed to retrieve the access token." + }; + } + + token = await tokenResponse.Secret.Decrypt(Program.ENCRYPTION); + } + else + token = temporarySecret; - var token = await tokenResponse.Secret.Decrypt(Program.ENCRYPTION); using (var request = new HttpRequestMessage(HttpMethod.Post, $"auth?authMethod={authMethod}")) { request.Headers.Add("Authorization", $"Bearer {token}"); diff --git a/app/MindWork AI Studio/Tools/ERIClient/IERIClient.cs b/app/MindWork AI Studio/Tools/ERIClient/IERIClient.cs index 0408e8d..80d8c4f 100644 --- a/app/MindWork AI Studio/Tools/ERIClient/IERIClient.cs +++ b/app/MindWork AI Studio/Tools/ERIClient/IERIClient.cs @@ -1,4 +1,3 @@ -using AIStudio.Settings; using AIStudio.Tools.ERIClient.DataModel; using AIStudio.Tools.Services; @@ -19,11 +18,11 @@ public interface IERIClient : IDisposable /// /// Authenticate the user to the ERI server. /// - /// The data source to use. /// The Rust service. + /// The temporary secret when adding a new data source, and the secret is not yet stored in the OS. /// The cancellation token. /// The authentication response. - public Task> AuthenticateAsync(IERIDataSource dataSource, RustService rustService, CancellationToken cancellationToken = default); + public Task> AuthenticateAsync(RustService rustService, string? temporarySecret = null, CancellationToken cancellationToken = default); /// /// Retrieves the data source information from the ERI server. diff --git a/app/MindWork AI Studio/Tools/Services/DataSourceService.cs b/app/MindWork AI Studio/Tools/Services/DataSourceService.cs index de59308..f545aca 100644 --- a/app/MindWork AI Studio/Tools/Services/DataSourceService.cs +++ b/app/MindWork AI Studio/Tools/Services/DataSourceService.cs @@ -113,7 +113,7 @@ public sealed class DataSourceService } this.logger.LogInformation($"Authenticating with ERI source '{source.Name}' (id={source.Id})..."); - var loginResult = await client.AuthenticateAsync(eriSource, this.rustService, cancellationTokenSource.Token); + var loginResult = await client.AuthenticateAsync(this.rustService, cancellationToken: cancellationTokenSource.Token); if (!loginResult.Successful) { this.logger.LogWarning($"Authentication with ERI source '{source.Name}' (id={source.Id}) failed. We skip this source. Reason: {loginResult.Message}"); diff --git a/app/MindWork AI Studio/wwwroot/changelog/v0.9.34.md b/app/MindWork AI Studio/wwwroot/changelog/v0.9.34.md new file mode 100644 index 0000000..6442ae4 --- /dev/null +++ b/app/MindWork AI Studio/wwwroot/changelog/v0.9.34.md @@ -0,0 +1,2 @@ +# v0.9.34, build 209 (2025-03-11 xx:xx UTC) +- Fixed another bug related to ERI server authentication when adding new servers. \ No newline at end of file