Перепиливание под чистый DDD

This commit is contained in:
Халимов Рустам
2026-03-22 23:59:33 +03:00
parent 5da1a2f45d
commit 6e532b021d
302 changed files with 3595 additions and 3679 deletions
@@ -0,0 +1,81 @@
using Carter;
using Knot.Shared.Kernel;
using Knot.Modules.Profiles.Application.Profiles.Avatar;
using Knot.Modules.Profiles.Application.Profiles.GetProfile;
using Knot.Modules.Profiles.Application.Profiles.Search;
using Knot.Modules.Profiles.Application.Profiles.UpdateProfile;
using Knot.Modules.Profiles.Application.Profiles.UpdateSettings;
using MediatR;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Mvc;
namespace Knot.Modules.Profiles.Presentation.Endpoints;
public sealed class ProfilesEndpoints : ICarterModule
{
public void AddRoutes(IEndpointRouteBuilder app)
{
var group = app.MapGroup("api/profiles").RequireAuthorization();
group.MapGet("search", async ([FromQuery] string q, ISender sender, CancellationToken ct) =>
{
var result = await sender.Send(new SearchProfilesQuery(q), ct);
return result.IsSuccess ? Results.Ok(result.Value) : Results.BadRequest(result.Error);
});
group.MapPut("settings", async ([FromBody] Knot.Modules.Profiles.Application.Profiles.DTOs.UpdateSettingsRequest request, ISender sender, IUserContext userContext, CancellationToken ct) =>
{
var result = await sender.Send(new UpdateSettingsCommand(userContext.UserId, request.HideStoryViews), ct);
return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound(result.Error);
});
group.MapPost("avatar", async (HttpRequest req, ISender sender, IUserContext userContext, CancellationToken ct) =>
{
if (!req.HasFormContentType) return Results.BadRequest("No file uploaded");
var form = await req.ReadFormAsync(ct);
var file = form.Files.FirstOrDefault();
if (file == null || file.Length == 0) return Results.BadRequest("No file uploaded");
using var stream = file.OpenReadStream();
var result = await sender.Send(new UploadAvatarCommand(userContext.UserId, stream, file.FileName, file.ContentType), ct);
return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound(result.Error);
}).DisableAntiforgery();
group.MapPost("avatar/crop", async (HttpRequest req, ISender sender, IUserContext userContext, CancellationToken ct) =>
{
if (!req.HasFormContentType) return Results.BadRequest("No file uploaded");
var form = await req.ReadFormAsync(ct);
var file = form.Files.FirstOrDefault();
if (file == null || file.Length == 0) return Results.BadRequest("No file uploaded");
int.TryParse(form["x"], out int x);
int.TryParse(form["y"], out int y);
int.TryParse(form["width"], out int width);
int.TryParse(form["height"], out int height);
using var stream = file.OpenReadStream();
var result = await sender.Send(new CropAvatarCommand(userContext.UserId, stream, file.FileName ?? "avatar.jpg", file.ContentType, x, y, width, height), ct);
return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound(result.Error);
}).DisableAntiforgery();
group.MapDelete("avatar", async (ISender sender, IUserContext userContext, CancellationToken ct) =>
{
var result = await sender.Send(new DeleteAvatarCommand(userContext.UserId), ct);
return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound(result.Error);
});
group.MapPut("profile", async ([FromBody] Knot.Modules.Profiles.Application.Profiles.DTOs.UpdateProfileRequest request, ISender sender, IUserContext userContext, CancellationToken ct) =>
{
var result = await sender.Send(new UpdateProfileCommand(userContext.UserId, request.DisplayName, request.Bio, request.Birthday), ct);
return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound(result.Error);
});
group.MapGet("{id:guid}", async (Guid id, ISender sender, CancellationToken ct) =>
{
var result = await sender.Send(new GetProfileQuery(id), ct);
return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound(result.Error);
});
}
}