Админка рабочая
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using Knot.Contracts.Settings.Application.Abstractions;
|
||||
using Knot.Contracts.Settings.Application.DTOs;
|
||||
using Knot.Modules.Admin.Application.Admin.Commands;
|
||||
@@ -11,7 +12,9 @@ using Microsoft.AspNetCore.Routing;
|
||||
|
||||
namespace Knot.Host.Presentation.Endpoints;
|
||||
|
||||
public record KlipyTestDto(string ApiKey, string AppName);
|
||||
public record KlipyTestDto(
|
||||
[property: JsonPropertyName("apiKey")] string ApiKey,
|
||||
[property: JsonPropertyName("appName")] string AppName);
|
||||
public record ResetPasswordRequest(string NewPassword);
|
||||
|
||||
public static class AdminEndpoints
|
||||
@@ -34,7 +37,16 @@ public static class AdminEndpoints
|
||||
|
||||
group.MapPost("settings/test-klipy", async ([FromBody] KlipyTestDto dto, ISender sender, CancellationToken ct) =>
|
||||
{
|
||||
Console.WriteLine($"[Admin] TestKlipy received: ApiKey={(string.IsNullOrEmpty(dto.ApiKey) ? "EMPTY" : "present")}, AppName={(string.IsNullOrEmpty(dto.AppName) ? "EMPTY" : dto.AppName)}");
|
||||
|
||||
if (string.IsNullOrEmpty(dto.ApiKey) || string.IsNullOrEmpty(dto.AppName))
|
||||
{
|
||||
Console.WriteLine($"[Admin] TestKlipy: Missing required fields - ApiKey={dto?.ApiKey}, AppName={dto?.AppName}");
|
||||
return Results.BadRequest(new { error = "ApiKey and AppName are required" });
|
||||
}
|
||||
|
||||
var result = await sender.Send(new TestKlipyConnectionCommand(dto.ApiKey, dto.AppName), ct);
|
||||
Console.WriteLine($"[Admin] TestKlipy result: IsSuccess={result.IsSuccess}, Error={result.Error?.Description}");
|
||||
return result.IsSuccess ? Results.Ok(new { success = true }) : Results.BadRequest(new { error = result.Error.Description });
|
||||
});
|
||||
|
||||
|
||||
@@ -2,11 +2,36 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using Knot.Modules.Klipy.Application.Abstractions;
|
||||
using Knot.Modules.Klipy.Infrastructure.External;
|
||||
|
||||
// Псевдонимы для устранения неоднозначности
|
||||
using ContractIKlipyClient = Knot.Contracts.Klipy.Application.Abstractions.IKlipyClient;
|
||||
using ModuleIKlipyClient = Knot.Modules.Klipy.Application.Abstractions.IKlipyClient;
|
||||
|
||||
namespace Knot.Modules.Klipy;
|
||||
|
||||
public static class DependencyInjection {
|
||||
public static IServiceCollection AddKlipyModule(this IServiceCollection services) {
|
||||
services.AddHttpClient<IKlipyClient, KlipyClient>();
|
||||
public static class DependencyInjection
|
||||
{
|
||||
public static IServiceCollection AddKlipyModule(this IServiceCollection services)
|
||||
{
|
||||
services.AddHttpClient<ModuleIKlipyClient, KlipyClient>();
|
||||
// Также регистрируем contract-интерфейс для Admin модуля
|
||||
services.AddScoped<ContractIKlipyClient>(sp =>
|
||||
new ContractKlipyClientAdapter(sp.GetRequiredService<ModuleIKlipyClient>()));
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Адаптер для преобразования между интерфейсами
|
||||
internal sealed class ContractKlipyClientAdapter : ContractIKlipyClient
|
||||
{
|
||||
private readonly ModuleIKlipyClient _inner;
|
||||
|
||||
public ContractKlipyClientAdapter(ModuleIKlipyClient inner)
|
||||
{
|
||||
_inner = inner;
|
||||
}
|
||||
|
||||
public async Task<bool> TestConnectionAsync(string apiKey, string appName, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await _inner.TestConnectionAsync(apiKey, appName, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,14 +20,21 @@ public sealed class KlipyClient : Knot.Modules.Klipy.Application.Abstractions.IK
|
||||
{
|
||||
try
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, $"https://api.klipy.com/api/v1/{appName}/gifs/trending?page=1&per_page=1&customer_id=knot_admin_test");
|
||||
request.Headers.Add("X-KLIPY-API-KEY", apiKey);
|
||||
var url = $"https://api.klipy.com/api/v1/{apiKey}/gifs/trending?page=1&per_page=1&customer_id={appName}&locale=en";
|
||||
Console.WriteLine($"[Klipy] TestConnection URL: {url}");
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
||||
request.Headers.Add("User-Agent", "KnotMessenger/1.0");
|
||||
request.Headers.Add("Accept", "application/json");
|
||||
|
||||
using var response = await _httpClient.SendAsync(request, ct);
|
||||
var responseBody = await response.Content.ReadAsStringAsync(ct);
|
||||
Console.WriteLine($"[Klipy] TestConnection response: {response.StatusCode}, body: {responseBody}");
|
||||
return response.IsSuccessStatusCode;
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[Klipy] TestConnection exception: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,5 +8,6 @@
|
||||
<ProjectReference Include="..\..\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||
<ProjectReference Include="..\..\Shared\Knot.Shared.Infrastructure\Knot.Shared.Infrastructure.csproj" />
|
||||
<ProjectReference Include="..\..\Contracts\Settings\Knot.Contracts.Settings.csproj" />
|
||||
<ProjectReference Include="..\..\Contracts\Klipy\Knot.Contracts.Klipy.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -15,8 +15,8 @@ export class HttpClient {
|
||||
|
||||
const isFormData = fetchOptions.body instanceof FormData;
|
||||
const computedHeaders: Record<string, string> = {
|
||||
...(this.token
|
||||
? { Authorization: this.token.startsWith('Basic ') ? this.token : `Bearer ${this.token}` }
|
||||
...(this.token
|
||||
? { Authorization: this.token.startsWith('Basic ') ? this.token : `Bearer ${this.token}` }
|
||||
: {}),
|
||||
...(fetchOptions.headers as Record<string, string>),
|
||||
};
|
||||
@@ -47,7 +47,13 @@ export class HttpClient {
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
|
||||
const jsonData = await response.json();
|
||||
// Handle empty responses (e.g., 200 OK with no body)
|
||||
const text = await response.text();
|
||||
if (!text) {
|
||||
return undefined as T;
|
||||
}
|
||||
|
||||
const jsonData = JSON.parse(text);
|
||||
return deepNormalize(jsonData);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user