Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1a03355e84 | |||
| f245bc94e1 | |||
| 7743c3178e | |||
| da141311ff | |||
| ab3d8e6e9a | |||
| 97bde73777 |
@@ -1,4 +1,5 @@
|
|||||||
using LiteCharms.Features.Shop.Notifications;
|
using LiteCharms.Features.Models;
|
||||||
|
using LiteCharms.Features.Shop.Notifications;
|
||||||
using LiteCharms.Features.Shop.Notifications.Events;
|
using LiteCharms.Features.Shop.Notifications.Events;
|
||||||
|
|
||||||
namespace LiteCharms.Features.Tests;
|
namespace LiteCharms.Features.Tests;
|
||||||
@@ -34,6 +35,23 @@ public class NotificationsFeatureTests(CommonFixture fixture, ITestOutputHelper
|
|||||||
foreach (var error in createResult.Errors) output.WriteLine(error.Message);
|
foreach (var error in createResult.Errors) output.WriteLine(error.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetNotifications_ShouldReturn_AllNotifications()
|
||||||
|
{
|
||||||
|
DateRange range = new()
|
||||||
|
{
|
||||||
|
From = DateOnly.FromDateTime(new DateTime(2026, 04, 01, 0, 0, 0, DateTimeKind.Utc)),
|
||||||
|
To = DateOnly.FromDateTime(DateTime.UtcNow),
|
||||||
|
MaxRecords = 10
|
||||||
|
};
|
||||||
|
|
||||||
|
var getResult = await notificationService.GetNotificationsAsync(range);
|
||||||
|
|
||||||
|
Assert.True(getResult.IsSuccess);
|
||||||
|
|
||||||
|
foreach (var error in getResult.Errors) output.WriteLine(error.Message);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ProcessEmailNotificationsEvent_ShouldSucceed()
|
public async Task ProcessEmailNotificationsEvent_ShouldSucceed()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using Amazon.Runtime;
|
||||||
|
using LiteCharms.Features.S3;
|
||||||
|
using LiteCharms.Features.S3.Configuration;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.Extensions;
|
||||||
|
|
||||||
|
public static class S3
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddGarageS3(this IServiceCollection services, IConfiguration configuration)
|
||||||
|
{
|
||||||
|
var optionsSection = configuration.GetSection(nameof(S3Settings));
|
||||||
|
services.Configure<S3Settings>(optionsSection);
|
||||||
|
|
||||||
|
var options = optionsSection.Get<S3Settings>()
|
||||||
|
?? throw new InvalidOperationException("S3 configuration section is missing.");
|
||||||
|
|
||||||
|
var credentials = new BasicAWSCredentials(options.AccessKey, options.SecretKey);
|
||||||
|
|
||||||
|
var s3Config = new AmazonS3Config
|
||||||
|
{
|
||||||
|
ServiceURL = options.ServiceUrl,
|
||||||
|
AuthenticationRegion = options.Region,
|
||||||
|
ForcePathStyle = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
services.AddSingleton<IAmazonS3>(new AmazonS3Client(credentials, s3Config));
|
||||||
|
services.AddScoped<S3Service>();
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -128,6 +128,16 @@
|
|||||||
<Using Include="FluentResults" />
|
<Using Include="FluentResults" />
|
||||||
<Using Include="Mediator" />
|
<Using Include="Mediator" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- Amazon S3 SDK -->
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="AWSSDK.Extensions.NetCore.Setup" Version="4.0.3.40" />
|
||||||
|
<PackageReference Include="AWSSDK.S3" Version="4.0.23.3" />
|
||||||
|
|
||||||
|
<!-- global Usings -->
|
||||||
|
<Using Include="Amazon.S3" />
|
||||||
|
<Using Include="Amazon.S3.Model" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<!-- Shared Usings -->
|
<!-- Shared Usings -->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
namespace LiteCharms.Features.S3.Configuration;
|
||||||
|
|
||||||
|
public class S3Settings
|
||||||
|
{
|
||||||
|
public string? ServiceUrl { get; set; }
|
||||||
|
|
||||||
|
public string? AccessKey { get; set; }
|
||||||
|
|
||||||
|
public string? SecretKey { get; set; }
|
||||||
|
|
||||||
|
public string? BucketName { get; set; }
|
||||||
|
|
||||||
|
public string? Region { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
namespace LiteCharms.Features.S3;
|
||||||
|
|
||||||
|
public class S3Service(IAmazonS3 amazonS3)
|
||||||
|
{
|
||||||
|
public async Task<Result<string>> UploadFileAsync(string bucketName, string fileName, Stream fileStream, string contentType, string cdnBaseUrl, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var putRequest = new PutObjectRequest
|
||||||
|
{
|
||||||
|
BucketName = bucketName,
|
||||||
|
Key = fileName,
|
||||||
|
InputStream = fileStream,
|
||||||
|
ContentType = contentType
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = await amazonS3.PutObjectAsync(putRequest, cancellationToken);
|
||||||
|
|
||||||
|
return response.HttpStatusCode != System.Net.HttpStatusCode.OK
|
||||||
|
? Result.Fail<string>($"Failed to upload {fileName} to S3.")
|
||||||
|
: Result.Ok(string.Format(cdnBaseUrl, bucketName, fileName));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<string>(new Error($"Error uploading {fileName} to S3: {ex.Message}").CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -63,8 +63,8 @@ public class NotificationService(IDbContextFactory<ShopDbContext> contextFactory
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var fromDate = range.From.ToDateTime(TimeOnly.MinValue);
|
var fromDate = range.From.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc);
|
||||||
var toDate = range.To.ToDateTime(TimeOnly.MaxValue);
|
var toDate = range.To.ToDateTime(TimeOnly.MaxValue, DateTimeKind.Utc);
|
||||||
|
|
||||||
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
@@ -96,12 +96,9 @@ public class NotificationService(IDbContextFactory<ShopDbContext> contextFactory
|
|||||||
return Result.Fail(new Error($"Notification with id {request.NotificationId} not found."));
|
return Result.Fail(new Error($"Notification with id {request.NotificationId} not found."));
|
||||||
|
|
||||||
notification.Processed = request.Processed;
|
notification.Processed = request.Processed;
|
||||||
|
notification.UpdatedAt = DateTime.UtcNow;
|
||||||
if (request.HasError)
|
notification.HasError = request.HasError;
|
||||||
{
|
notification.Errors = request.Errors;
|
||||||
notification.HasError = request.HasError;
|
|
||||||
notification.Errors = request.Errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
return await context.SaveChangesAsync(cancellationToken) > 0
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
? Result.Ok()
|
? Result.Ok()
|
||||||
|
|||||||
Reference in New Issue
Block a user