From 60d3cf12ae5cb8c378008eb84d7750e4af9b7edd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A5=D0=B0=D0=BB=D0=B8=D0=BC=D0=BE=D0=B2=20=D0=A0=D1=83?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D0=BC?= Date: Tue, 31 Mar 2026 00:38:34 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A1=D0=B1=D0=BE=D1=80=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Presentation/Endpoints/AdminEndpoints.cs | 8 +++--- .../Presentation/Endpoints/ChatsEndpoints.cs | 18 ++++++------ .../Endpoints/MessagesEndpoints.cs | 6 ++-- .../Endpoints/FederationEndpoints.cs | 28 +++++++++---------- .../Endpoints/ContactsEndpoints.cs | 8 +++--- .../Endpoints/StoriesEndpoints.cs | 10 +++---- 6 files changed, 39 insertions(+), 39 deletions(-) diff --git a/backend/src/Modules/Admin/Presentation/Endpoints/AdminEndpoints.cs b/backend/src/Modules/Admin/Presentation/Endpoints/AdminEndpoints.cs index 5f5c37f..6654af9 100644 --- a/backend/src/Modules/Admin/Presentation/Endpoints/AdminEndpoints.cs +++ b/backend/src/Modules/Admin/Presentation/Endpoints/AdminEndpoints.cs @@ -44,7 +44,7 @@ public static class AdminEndpoints return Results.Ok(result.Value); }); - group.MapPost("users/{userId:guid}/reset-password", async (Guid userId, [FromBody] ResetPasswordRequest dto, ISender sender, CancellationToken ct) => + group.MapPost("users/{userId:guid}/reset-password", async ([FromRoute] Guid userId, [FromBody] ResetPasswordRequest dto, ISender sender, CancellationToken ct) => { var result = await sender.Send(new ResetUserPasswordCommand(userId, dto.NewPassword), ct); if (result.IsFailure) @@ -55,13 +55,13 @@ public static class AdminEndpoints return Results.Ok(result.Value); }); - group.MapPost("users/{userId:guid}/ban", async (Guid userId, ISender sender, CancellationToken ct) => + group.MapPost("users/{userId:guid}/ban", async ([FromRoute] Guid userId, ISender sender, CancellationToken ct) => { var result = await sender.Send(new BanUserCommand(userId), ct); return result.IsSuccess ? Results.Ok() : Results.BadRequest(new { error = result.Error.Description }); }); - group.MapPost("users/{userId:guid}/unban", async (Guid userId, ISender sender, CancellationToken ct) => + group.MapPost("users/{userId:guid}/unban", async ([FromRoute] Guid userId, ISender sender, CancellationToken ct) => { var result = await sender.Send(new UnbanUserCommand(userId), ct); return result.IsSuccess ? Results.Ok() : Results.BadRequest(new { error = result.Error.Description }); @@ -77,7 +77,7 @@ public static class AdminEndpoints return Results.Ok(result.Value); }); - group.MapGet("users/{id:guid}", async (Guid id, ISender sender, CancellationToken ct) => + group.MapGet("users/{id:guid}", async ([FromRoute] Guid id, ISender sender, CancellationToken ct) => { var result = await sender.Send(new GetUserDetailsQuery(id), ct); return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound("User not found"); diff --git a/backend/src/Modules/Conversations/Presentation/Endpoints/ChatsEndpoints.cs b/backend/src/Modules/Conversations/Presentation/Endpoints/ChatsEndpoints.cs index 6de2a98..1d9d1fd 100644 --- a/backend/src/Modules/Conversations/Presentation/Endpoints/ChatsEndpoints.cs +++ b/backend/src/Modules/Conversations/Presentation/Endpoints/ChatsEndpoints.cs @@ -74,7 +74,7 @@ public static class ChatsEndpoints return Results.Ok(chatResult.Value); }); - group.MapPut("{id:guid}", async (Guid id, [FromBody] UpdateChatRequest request, ISender sender, IUserContext userContext, CancellationToken ct) => + group.MapPut("{id:guid}", async ([FromRoute] Guid id, [FromBody] UpdateChatRequest request, ISender sender, IUserContext userContext, CancellationToken ct) => { var result = await sender.Send(new UpdateChatCommand(id, userContext.UserId, request.Name, request.Description), ct); if (result.IsFailure) return Results.NotFound(); @@ -83,7 +83,7 @@ public static class ChatsEndpoints return Results.Ok(chatResult.Value); }); - group.MapDelete("{id:guid}", async (Guid id, ISender sender, IUserContext userContext, CancellationToken ct) => + group.MapDelete("{id:guid}", async ([FromRoute] Guid id, ISender sender, IUserContext userContext, CancellationToken ct) => { var result = await sender.Send(new LeaveOrDeleteChatCommand(id, userContext.UserId), ct); if (result.IsFailure) @@ -94,19 +94,19 @@ public static class ChatsEndpoints return Results.Ok(result.Value); }); - group.MapPost("{id:guid}/clear", async (Guid id, ISender sender, IUserContext userContext, CancellationToken ct) => + group.MapPost("{id:guid}/clear", async ([FromRoute] Guid id, ISender sender, IUserContext userContext, CancellationToken ct) => { var result = await sender.Send(new ClearChatCommand(id, userContext.UserId), ct); return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound(); }); - group.MapPost("{id:guid}/pin", async (Guid id, ISender sender, IUserContext userContext, CancellationToken ct) => + group.MapPost("{id:guid}/pin", async ([FromRoute] Guid id, ISender sender, IUserContext userContext, CancellationToken ct) => { var result = await sender.Send(new TogglePinCommand(id, userContext.UserId), ct); return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound(); }); - group.MapPost("{id:guid}/members", async (Guid id, [FromBody] AddMembersRequest request, ISender sender, IUserContext userContext, CancellationToken ct) => + group.MapPost("{id:guid}/members", async ([FromRoute] Guid id, [FromBody] AddMembersRequest request, ISender sender, IUserContext userContext, CancellationToken ct) => { var result = await sender.Send(new AddMembersCommand(id, userContext.UserId, request.UserIds.ToList()), ct); if (result.IsFailure) return Results.NotFound(); @@ -115,7 +115,7 @@ public static class ChatsEndpoints return Results.Ok(chatResult.Value); }); - group.MapDelete("{id:guid}/members/{userId:guid}", async (Guid id, Guid userId, ISender sender, IUserContext userContext, CancellationToken ct) => + group.MapDelete("{id:guid}/members/{userId:guid}", async ([FromRoute] Guid id, [FromRoute] Guid userId, ISender sender, IUserContext userContext, CancellationToken ct) => { var result = await sender.Send(new RemoveMemberCommand(id, userContext.UserId, userId), ct); if (result.IsFailure) return Results.NotFound(); @@ -124,7 +124,7 @@ public static class ChatsEndpoints return Results.Ok(chatResult.Value); }); - group.MapPost("{id:guid}/avatar", async (Guid id, HttpRequest req, ISender sender, IUserContext userContext, CancellationToken ct) => + group.MapPost("{id:guid}/avatar", async ([FromRoute] Guid id, HttpRequest req, ISender sender, IUserContext userContext, CancellationToken ct) => { if (!req.HasFormContentType) return Results.BadRequest("No file"); var form = await req.ReadFormAsync(ct); @@ -139,7 +139,7 @@ public static class ChatsEndpoints return Results.Ok(chatResult.Value); }).DisableAntiforgery(); - group.MapPost("{id:guid}/avatar/crop", async (Guid id, HttpRequest req, ISender sender, IUserContext userContext, CancellationToken ct) => + group.MapPost("{id:guid}/avatar/crop", async ([FromRoute] Guid id, HttpRequest req, ISender sender, IUserContext userContext, CancellationToken ct) => { if (!req.HasFormContentType) return Results.BadRequest("No file"); var form = await req.ReadFormAsync(ct); @@ -159,7 +159,7 @@ public static class ChatsEndpoints return Results.Ok(chatResult.Value); }).DisableAntiforgery(); - group.MapDelete("{id:guid}/avatar", async (Guid id, ISender sender, IUserContext userContext, CancellationToken ct) => + group.MapDelete("{id:guid}/avatar", async ([FromRoute] Guid id, ISender sender, IUserContext userContext, CancellationToken ct) => { var result = await sender.Send(new RemoveGroupAvatarCommand(id, userContext.UserId), ct); if (result.IsFailure) return Results.NotFound(); diff --git a/backend/src/Modules/Conversations/Presentation/Endpoints/MessagesEndpoints.cs b/backend/src/Modules/Conversations/Presentation/Endpoints/MessagesEndpoints.cs index 54dd276..6e89b10 100644 --- a/backend/src/Modules/Conversations/Presentation/Endpoints/MessagesEndpoints.cs +++ b/backend/src/Modules/Conversations/Presentation/Endpoints/MessagesEndpoints.cs @@ -19,7 +19,7 @@ public static class MessagesEndpoints { var group = app.MapGroup("api/messages").RequireAuthorization(); - group.MapGet("chat/{chatId:guid}", async (Guid chatId, [FromQuery] string? cursor, ISender sender, IUserContext userContext, CancellationToken ct) => + group.MapGet("chat/{chatId:guid}", async ([FromRoute] Guid chatId, [FromQuery] string? cursor, ISender sender, IUserContext userContext, CancellationToken ct) => { var result = await sender.Send(new GetMessagesQuery(userContext.UserId, chatId, cursor), ct); return result.IsSuccess ? Results.Ok(result.Value) : Results.BadRequest(result.Error.Description); @@ -49,13 +49,13 @@ public static class MessagesEndpoints return Results.Ok(result.Value); }).DisableAntiforgery(); - group.MapGet("chat/{chatId:guid}/shared", async (Guid chatId, [FromQuery] string? type, ISender sender, IUserContext userContext, CancellationToken ct) => + group.MapGet("chat/{chatId:guid}/shared", async ([FromRoute] Guid chatId, [FromQuery] string? type, ISender sender, IUserContext userContext, CancellationToken ct) => { var result = await sender.Send(new GetSharedMediaQuery(userContext.UserId, chatId, type), ct); return result.IsSuccess ? Results.Ok(result.Value) : Results.BadRequest(result.Error.Description); }); - group.MapPost("chat/{chatId:guid}", async (Guid chatId, [FromBody] SendMessageRequest request, ISender sender, IUserContext userContext, CancellationToken ct) => + group.MapPost("chat/{chatId:guid}", async ([FromRoute] Guid chatId, [FromBody] SendMessageRequest request, ISender sender, IUserContext userContext, CancellationToken ct) => { var attachments = request.Attachments?.Select(a => new AttachmentRequest(a.Type, a.Url, a.FileName, a.FileSize)).ToList(); diff --git a/backend/src/Modules/Federation/Presentation/Endpoints/FederationEndpoints.cs b/backend/src/Modules/Federation/Presentation/Endpoints/FederationEndpoints.cs index c2be4ea..52f4420 100644 --- a/backend/src/Modules/Federation/Presentation/Endpoints/FederationEndpoints.cs +++ b/backend/src/Modules/Federation/Presentation/Endpoints/FederationEndpoints.cs @@ -1,15 +1,15 @@ -using MediatR; +using System; +using Host.Application.Federation.Commands; +using Knot.Contracts.Settings.Application.Abstractions; +using Knot.Contracts.Settings.Application.DTOs; +using Knot.Modules.Federation.Application.Abstractions; using Knot.Shared.Kernel.Constants; +using Knot.Shared.Kernel.Storage; +using MediatR; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Routing; -using System; -using Host.Application.Federation.Commands; -using Knot.Modules.Federation.Application.Abstractions; -using Knot.Shared.Kernel.Storage; -using Knot.Contracts.Settings.Application.Abstractions; -using Knot.Contracts.Settings.Application.DTOs; namespace Host.Endpoints; @@ -21,7 +21,7 @@ public static class FederationEndpoints public static void MapFederationEndpoints(this WebApplication app) { var group = app.MapGroup(Routes.ApiFederation); - + group.MapPost("/handshake", async ([FromBody] HandshakeRequest request, ISender sender, CancellationToken ct) => { var result = await sender.Send(new HandshakeFederationCommand(request), ct); @@ -34,30 +34,30 @@ public static class FederationEndpoints return result.IsSuccess ? Results.Accepted() : Results.BadRequest(new { error = result.Error.Description }); }); - group.MapGet("/resolve/{username}", async (string username, ISender sender, CancellationToken ct) => + group.MapGet("/resolve/{username}", async ([FromRoute] string username, ISender sender, CancellationToken ct) => { var result = await sender.Send(new ResolveUserCommand(username), ct); return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound(new { error = result.Error.Description }); }); - group.MapGet("/proxy/{id}", async (string id, [FromHeader(Name = "X-Knot-Signature")] string signature, [FromHeader(Name = "X-Knot-Domain")] string senderDomain, [FromServices] IFileStorageService storage, [FromServices] ISettingsService settingsService, CancellationToken ct) => + group.MapGet("/proxy/{id}", async ([FromRoute] string id, [FromHeader(Name = "X-Knot-Signature")] string signature, [FromHeader(Name = "X-Knot-Domain")] string senderDomain, [FromServices] IFileStorageService storage, [FromServices] ISettingsService settingsService, CancellationToken ct) => { // 1. Валидация подписи (упрощенно) var settings = await settingsService.GetSettingsAsync(ct); var senderConfig = settings.Federation.AllowedDomains.FirstOrDefault(d => d.Domain.Equals(senderDomain, StringComparison.OrdinalIgnoreCase)); - + if (senderConfig == null || string.IsNullOrEmpty(senderConfig.PublicKey)) return Results.Forbid(); // В реальном коде здесь проверка RSA подписи параметров запроса (URL + Domain) - + // 2. Стриминг файла первоисточника - try + try { var (stream, contentType, fileName) = await storage.DownloadFileAsync(id); return Results.File(stream, contentType, fileName, enableRangeProcessing: true); } - catch + catch { return Results.NotFound(); } diff --git a/backend/src/Modules/Relations/Presentation/Endpoints/ContactsEndpoints.cs b/backend/src/Modules/Relations/Presentation/Endpoints/ContactsEndpoints.cs index 83748b7..2956312 100644 --- a/backend/src/Modules/Relations/Presentation/Endpoints/ContactsEndpoints.cs +++ b/backend/src/Modules/Relations/Presentation/Endpoints/ContactsEndpoints.cs @@ -29,7 +29,7 @@ public static class ContactsEndpoints return result.IsSuccess ? Results.Ok(result.Value) : Results.BadRequest(result.Error); }); - group.MapGet("status/{userId:guid}", async (Guid userId, ISender sender, IUserContext userContext, IContactsDbContext context, CancellationToken ct) => + group.MapGet("status/{userId:guid}", async ([FromRoute] Guid userId, ISender sender, IUserContext userContext, [FromServices] IContactsDbContext context, CancellationToken ct) => { var contact = await context.Contacts .FirstOrDefaultAsync(c => @@ -74,19 +74,19 @@ public static class ContactsEndpoints return result.IsSuccess ? Results.Ok(new { status = "pending" }) : Results.BadRequest(result.Error.Description); }); - group.MapPost("{id:guid}/accept", async (Guid id, ISender sender, IUserContext userContext, CancellationToken ct) => + group.MapPost("{id:guid}/accept", async ([FromRoute] Guid id, ISender sender, IUserContext userContext, CancellationToken ct) => { var result = await sender.Send(new AcceptContactRequestCommand(userContext.UserId, id), ct); return result.IsSuccess ? Results.Ok(new { id = result.Value }) : Results.NotFound(result.Error.Description); }); - group.MapPost("{id:guid}/decline", async (Guid id, ISender sender, IUserContext userContext, CancellationToken ct) => + group.MapPost("{id:guid}/decline", async ([FromRoute] Guid id, ISender sender, IUserContext userContext, CancellationToken ct) => { var result = await sender.Send(new DeclineContactRequestCommand(userContext.UserId, id), ct); return result.IsSuccess ? Results.Ok(new { success = true }) : Results.NotFound(result.Error.Description); }); - group.MapDelete("{id:guid}", async (Guid id, ISender sender, IUserContext userContext, CancellationToken ct) => + group.MapDelete("{id:guid}", async ([FromRoute] Guid id, ISender sender, IUserContext userContext, CancellationToken ct) => { var result = await sender.Send(new RemoveContactCommand(userContext.UserId, id), ct); return result.IsSuccess ? Results.Ok(new SuccessResponse(true)) : Results.NotFound(result.Error.Description); diff --git a/backend/src/Modules/Stories/Presentation/Endpoints/StoriesEndpoints.cs b/backend/src/Modules/Stories/Presentation/Endpoints/StoriesEndpoints.cs index 3e2744c..fb68d06 100644 --- a/backend/src/Modules/Stories/Presentation/Endpoints/StoriesEndpoints.cs +++ b/backend/src/Modules/Stories/Presentation/Endpoints/StoriesEndpoints.cs @@ -33,7 +33,7 @@ public static class StoriesEndpoints return Results.Ok(new { id = result.Value }); }); - group.MapPost("video", async (HttpRequest req, ISender sender, IUserContext userContext, IFileStorageService fileStorage, CancellationToken ct) => + group.MapPost("video", async (HttpRequest req, ISender sender, IUserContext userContext, [FromServices] IFileStorageService fileStorage, CancellationToken ct) => { if (!req.HasFormContentType) return Results.BadRequest("No file uploaded"); var form = await req.ReadFormAsync(ct); @@ -45,26 +45,26 @@ public static class StoriesEndpoints return Results.Ok(new { url = $"/api/files/{fileId}" }); }).DisableAntiforgery(); - group.MapGet("user/{userId:guid}", async (Guid userId, ISender sender, IUserContext userContext, CancellationToken ct) => + group.MapGet("user/{userId:guid}", async ([FromRoute] Guid userId, ISender sender, IUserContext userContext, CancellationToken ct) => { var result = await sender.Send(new GetUserStoriesQuery(userContext.UserId, userId), ct); return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound(); }); - group.MapPost("{id:guid}/view", async (Guid id, ISender sender, IUserContext userContext, CancellationToken ct) => + group.MapPost("{id:guid}/view", async ([FromRoute] Guid id, ISender sender, IUserContext userContext, CancellationToken ct) => { var result = await sender.Send(new ViewStoryCommand(userContext.UserId, id), ct); return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound(); }); - group.MapGet("{id:guid}/viewers", async (Guid id, ISender sender, IUserContext userContext, CancellationToken ct) => + group.MapGet("{id:guid}/viewers", async ([FromRoute] Guid id, ISender sender, IUserContext userContext, CancellationToken ct) => { var result = await sender.Send(new GetStoryViewersQuery(userContext.UserId, id), ct); if (result.IsFailure) return result.Error.Code == "Unauthorized" ? Results.Forbid() : Results.NotFound(); return Results.Ok(result.Value); }); - group.MapDelete("{id:guid}", async (Guid id, ISender sender, IUserContext userContext, CancellationToken ct) => + group.MapDelete("{id:guid}", async ([FromRoute] Guid id, ISender sender, IUserContext userContext, CancellationToken ct) => { var result = await sender.Send(new DeleteStoryCommand(userContext.UserId, id), ct); if (result.IsFailure) return result.Error.Code == "Unauthorized" ? Results.Forbid() : Results.NotFound();