Adds ChangeBanner for Creators
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
namespace Hutopy.Application.Common.Interfaces;
|
||||
|
||||
public interface IAzureBlobStorageService
|
||||
public interface IBlobStorage
|
||||
{
|
||||
Task<string> UploadFileAsync(string containerName, string blobName, Stream stream, string contentType,
|
||||
CancellationToken ct = default);
|
||||
@@ -1,6 +1,5 @@
|
||||
using Hutopy.Application.AzureBlobStorage.Constants;
|
||||
using Hutopy.Application.Common.Interfaces;
|
||||
using Hutopy.Application.Utils;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Hutopy.Application.Users.Commands;
|
||||
@@ -16,19 +15,17 @@ public class UploadProfilePictureCommand : IRequest<IResult>
|
||||
public class UploadProfilePictureCommandHandler(
|
||||
IHttpContextAccessor contextAccessor,
|
||||
IIdentityService identityService,
|
||||
IAzureBlobStorageService azureBlobStorageService) : IRequestHandler<UploadProfilePictureCommand, IResult>
|
||||
IBlobStorage blobStorage) : IRequestHandler<UploadProfilePictureCommand, IResult>
|
||||
{
|
||||
public async Task<IResult> Handle(UploadProfilePictureCommand request, CancellationToken ct)
|
||||
{
|
||||
var contentType = contextAccessor.EnsureContentType();
|
||||
|
||||
var identityUser = await identityService.GetCurrentUserAsync();
|
||||
|
||||
var url = await azureBlobStorageService.UploadFileAsync(
|
||||
var url = await blobStorage.UploadFileAsync(
|
||||
ContainerNames.Users,
|
||||
$"{identityUser.Id}/{SubDirectoryNames.Profile}/{CommonFileNames.ProfilePicture}",
|
||||
request.File.OpenReadStream(),
|
||||
contentType,
|
||||
request.File.ContentType,
|
||||
ct);
|
||||
|
||||
await identityService.UpdateCurrentUserPortraitUrlAsync(url);
|
||||
|
||||
@@ -7,7 +7,7 @@ public record GetCurrentUserProfilePictureQuery : IRequest<Stream>;
|
||||
|
||||
public class GetCurrentUserProfilePictureQueryHandler(
|
||||
IIdentityService identityService,
|
||||
IAzureBlobStorageService azureBlobStorageService
|
||||
IBlobStorage blobStorage
|
||||
)
|
||||
: IRequestHandler<GetCurrentUserProfilePictureQuery, Stream>
|
||||
{
|
||||
@@ -15,7 +15,7 @@ public class GetCurrentUserProfilePictureQueryHandler(
|
||||
{
|
||||
var identityUser = await identityService.GetCurrentUserAsync();
|
||||
|
||||
return await azureBlobStorageService.DownloadFileAsync(
|
||||
return await blobStorage.DownloadFileAsync(
|
||||
ContainerNames.Users,
|
||||
$"{identityUser.Id.ToString()}/{SubDirectoryNames.Profile}/{CommonFileNames.ProfilePicture}",
|
||||
cancellationToken);
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Hutopy.Application.Utils;
|
||||
|
||||
public static class HttpContextAccessorExtensions
|
||||
{
|
||||
public static HttpContext EnsureHttpContext(this IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
if (httpContextAccessor.HttpContext == null)
|
||||
{
|
||||
throw new InvalidOperationException("HttpContext is null.");
|
||||
}
|
||||
|
||||
return httpContextAccessor.HttpContext;
|
||||
}
|
||||
|
||||
public static string EnsureContentType(this IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
var httpContext = EnsureHttpContext(httpContextAccessor);
|
||||
var contentType = httpContext.Request.ContentType;
|
||||
|
||||
if (string.IsNullOrEmpty(contentType))
|
||||
{
|
||||
throw new InvalidOperationException("Content-Type header is missing.");
|
||||
}
|
||||
|
||||
return contentType;
|
||||
}
|
||||
}
|
||||
@@ -7,13 +7,14 @@ using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Hutopy.Infrastructure.AzureBlob;
|
||||
|
||||
public class AzureBlobStorageService : IAzureBlobStorageService
|
||||
public class AzureBlobStorage : IBlobStorage
|
||||
{
|
||||
private const long MaxUploadSize = 10 * 1024 * 1024; // 10 MB in bytes
|
||||
|
||||
private readonly BlobServiceClient _blobServiceClient;
|
||||
private readonly ILogger<AzureBlobStorageService> _logger;
|
||||
private readonly long _maxUploadSize = 10 * 1024 * 1024; // 10 MB in bytes
|
||||
private readonly ILogger<AzureBlobStorage> _logger;
|
||||
|
||||
public AzureBlobStorageService(IConfiguration configuration, ILogger<AzureBlobStorageService> logger)
|
||||
public AzureBlobStorage(IConfiguration configuration, ILogger<AzureBlobStorage> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
var connectionString = configuration["Azure-Blob-Connection-String"] ?? "";
|
||||
@@ -37,12 +38,12 @@ public class AzureBlobStorageService : IAzureBlobStorageService
|
||||
stream.Position = 0;
|
||||
|
||||
// Check if the file size exceeds the maximum upload size
|
||||
if (stream.Length > _maxUploadSize)
|
||||
if (stream.Length > MaxUploadSize)
|
||||
{
|
||||
_logger.LogError(
|
||||
$"Blob storage: File size exceeds the maximum allowed size of {_maxUploadSize} bytes.");
|
||||
$"Blob storage: File size exceeds the maximum allowed size of {MaxUploadSize} bytes.");
|
||||
throw new InvalidOperationException(
|
||||
$"Blob storage: File size exceeds the maximum allowed size of {_maxUploadSize} bytes.");
|
||||
$"Blob storage: File size exceeds the maximum allowed size of {MaxUploadSize} bytes.");
|
||||
}
|
||||
|
||||
// Validate content type
|
||||
@@ -52,7 +52,7 @@ public static class DependencyInjection
|
||||
|
||||
// Singleton services
|
||||
services.AddSingleton(TimeProvider.System);
|
||||
services.AddSingleton<IAzureBlobStorageService, AzureBlobStorageService>();
|
||||
services.AddSingleton<IBlobStorage, AzureBlobStorage>();
|
||||
|
||||
// Scoped services
|
||||
services.AddScoped<IIdentityService, IdentityService>();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using FastEndpoints;
|
||||
using Hutopy.Application.AzureBlobStorage.Constants;
|
||||
using Hutopy.Application.Common.Interfaces;
|
||||
using Hutopy.Application.Utils;
|
||||
using Hutopy.Web.Features.Contents.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
@@ -14,7 +13,7 @@ public record ChangeBannerRequest(
|
||||
public class ChangeBannerHandler(
|
||||
IHttpContextAccessor contextAccessor,
|
||||
ContentDbContext context,
|
||||
IAzureBlobStorageService azureBlobStorageService)
|
||||
IBlobStorage blobStorage)
|
||||
: Endpoint<ChangeBannerRequest>
|
||||
{
|
||||
public override void Configure()
|
||||
@@ -29,21 +28,27 @@ public class ChangeBannerHandler(
|
||||
var creator = await context
|
||||
.Creators
|
||||
.Include(c => c.StoredDataUrls)
|
||||
.SingleAsync(
|
||||
.SingleOrDefaultAsync(
|
||||
c => c.Id == request.CreatorId,
|
||||
cancellationToken: ct);
|
||||
|
||||
var contentType = contextAccessor.EnsureContentType();
|
||||
|
||||
var blobUrl = await azureBlobStorageService.UploadFileAsync(
|
||||
if (creator is null)
|
||||
{
|
||||
await SendNotFoundAsync(ct);
|
||||
return;
|
||||
}
|
||||
|
||||
var blobUrl = await blobStorage.UploadFileAsync(
|
||||
ContainerNames.Users,
|
||||
$"{request.CreatorId}/{SubDirectoryNames.Profile}/{CommonFileNames.BannerPicture}",
|
||||
request.File.OpenReadStream(),
|
||||
contentType,
|
||||
request.File.ContentType,
|
||||
ct);
|
||||
|
||||
|
||||
creator.StoredDataUrls.BannerPictureUrl = blobUrl;
|
||||
|
||||
await context.SaveChangesAsync(ct);
|
||||
|
||||
|
||||
await SendOkAsync(blobUrl, ct);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ public sealed class PostContentRequestValidator : Validator<PostContentRequest>
|
||||
}
|
||||
|
||||
public sealed class PostContent(
|
||||
IAzureBlobStorageService blobStorage,
|
||||
IBlobStorage blobStorage,
|
||||
ContentDbContext context)
|
||||
: Endpoint<PostContentRequest>
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user