many fixes and improvements - rework for modules/ and common/

feat(emailer): add Postmark and Resend providers
This commit is contained in:
2025-06-06 12:21:43 -04:00
parent 31ba18fa8d
commit 25b94d3e02
313 changed files with 6586 additions and 18260 deletions

View File

@@ -0,0 +1,73 @@
using Hutopy.Infrastructure.BlobStorage.Contracts;
using Hutopy.Infrastructure.Security;
using Hutopy.Modules.Identity.Data;
namespace Hutopy.Modules.Identity.Handlers;
[PublicAPI]
public record ChangePortraitRequest(
IFormFile File);
[PublicAPI]
public record ChangePortraitResponse(
string BlobUrl);
[PublicAPI]
public sealed class ChangePortraitRequestValidator : Validator<ChangePortraitRequest>
{
public ChangePortraitRequestValidator()
{
RuleFor(x => x.File)
.NotNull()
.NotEmpty();
}
}
[PublicAPI]
public class ChangePortraitHandler(
UserManager userManager,
IBlobStorage blobStorage)
: Endpoint<ChangePortraitRequest, ChangePortraitResponse>
{
public override void Configure()
{
Post("/api/users/portrait");
Options(o => o.WithTags("Users"));
AllowFileUploads();
}
public override async Task HandleAsync(
ChangePortraitRequest request,
CancellationToken ct)
{
var user = await userManager.FindByIdAsync(HttpContext.User.GetUserId().ToString());
if (user is null)
{
await SendNotFoundAsync(ct);
return;
}
var blobUrl = await blobStorage.UploadFileAsync(
ContainerNames.Users,
$"{user.Id}/{SubDirectoryNames.Profile}/{CommonFileNames.ProfilePicture}",
request.File.OpenReadStream(),
request.File.ContentType,
ct);
user.PortraitUrl = blobUrl;
var result = await userManager.UpdateAsync(user);
if (result.Succeeded)
{
await SendOkAsync(
new ChangePortraitResponse(blobUrl),
ct);
}
else
{
await SendUnauthorizedAsync(ct);
}
}
}