Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 516062ed5d | |||
| 16832ec214 | |||
| cf439c5006 | |||
| bf36bb6bbc | |||
| 00d43c8f10 | |||
| 40a5f94941 | |||
| 9cb4b8264d | |||
| ddd823afab | |||
| 6418d27f5a | |||
| 9b15e296df |
@@ -11,7 +11,7 @@
|
||||
<!-- Quartz Scheduler-->
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Bogus" Version="35.6.5" />
|
||||
<PackageReference Include="Meziantou.Analyzer" Version="3.0.103">
|
||||
<PackageReference Include="Meziantou.Analyzer" Version="3.0.104">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
+1
-5
@@ -12,11 +12,7 @@
|
||||
<PackageReference Include="coverlet.collector" Version="10.0.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Mediator.SourceGenerator" Version="3.0.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.6.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
<!-- Quartz Scheduler-->
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Humanizer" Version="3.0.10" />
|
||||
<PackageReference Include="Meziantou.Analyzer" Version="3.0.103">
|
||||
<PackageReference Include="Meziantou.Analyzer" Version="3.0.104">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -43,7 +43,7 @@ public sealed class OrderService(IDbContextFactory<MidrandBooksDbContext> contex
|
||||
if (!await context.Orders.AnyAsync(o => o.Id == orderId, cancellationToken))
|
||||
return Result.Fail<long>("Order not found.");
|
||||
|
||||
if(!await context.Books.AnyAsync(ab => ab.Id == request.AuthorBookId, cancellationToken))
|
||||
if (!await context.Books.AnyAsync(ab => ab.Id == request.AuthorBookId, cancellationToken))
|
||||
return Result.Fail<long>("Author book not found.");
|
||||
|
||||
if (!await context.Prices.AnyAsync(pp => pp.Id == request.ProductPriceId, cancellationToken))
|
||||
@@ -51,7 +51,7 @@ public sealed class OrderService(IDbContextFactory<MidrandBooksDbContext> contex
|
||||
|
||||
var existingItem = await context.OrderItems.FirstOrDefaultAsync(i => i.ProductPriceId == request.ProductPriceId && i.OrderId == orderId, cancellationToken);
|
||||
|
||||
if(existingItem is not null)
|
||||
if (existingItem is not null)
|
||||
{
|
||||
existingItem.Quantity += request.Quantity;
|
||||
|
||||
@@ -82,7 +82,7 @@ public sealed class OrderService(IDbContextFactory<MidrandBooksDbContext> contex
|
||||
{
|
||||
try
|
||||
{
|
||||
if(items.Length == 0)
|
||||
if (items.Length == 0)
|
||||
return Result.Fail("No items to add.");
|
||||
|
||||
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||
@@ -203,13 +203,33 @@ public sealed class OrderService(IDbContextFactory<MidrandBooksDbContext> contex
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask<Result<OrderItem[]>> GetOrderItemsAsync(long orderId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||
|
||||
var orderItems = await context.OrderItems
|
||||
.Where(o => o.OrderId == orderId)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return orderItems.Count > 0
|
||||
? Result.Ok(orderItems.Select(i => i.ToModel()).ToArray())
|
||||
: Result.Fail<OrderItem[]>($"Order items not found for order ID {orderId}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask<Result<Order[]>> GetOrdersByCustomerAsync(long customerId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||
|
||||
if(!await context.Customers.AnyAsync(c => c.Id == customerId, cancellationToken))
|
||||
if (!await context.Customers.AnyAsync(c => c.Id == customerId, cancellationToken))
|
||||
return Result.Fail<Order[]>("Customer not found.");
|
||||
|
||||
var orders = await context.Orders
|
||||
@@ -276,16 +296,16 @@ public sealed class OrderService(IDbContextFactory<MidrandBooksDbContext> contex
|
||||
{
|
||||
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||
|
||||
if(!await context.Orders.AnyAsync(o => o.Id == orderId, cancellationToken))
|
||||
if (!await context.Orders.AnyAsync(o => o.Id == orderId, cancellationToken))
|
||||
return Result.Fail("Order not found.");
|
||||
|
||||
if(!await context.Addresses.AnyAsync(a => a.Id == request.AddressId, cancellationToken))
|
||||
if (!await context.Addresses.AnyAsync(a => a.Id == request.AddressId, cancellationToken))
|
||||
return Result.Fail("Address not found.");
|
||||
|
||||
if(!await context.ShippingProviders.AnyAsync(sp => sp.Id == request.ShippingProviderId && sp.Enabled, cancellationToken))
|
||||
if (!await context.ShippingProviders.AnyAsync(sp => sp.Id == request.ShippingProviderId && sp.Enabled, cancellationToken))
|
||||
return Result.Fail("Shipping provider not found or disabled.");
|
||||
|
||||
if(await context.Shippings.AnyAsync(s => s.OrderId == orderId, cancellationToken))
|
||||
if (await context.Shippings.AnyAsync(s => s.OrderId == orderId, cancellationToken))
|
||||
return Result.Fail("Shipping already exists for this order.");
|
||||
|
||||
var shipping = context.Shippings.Add(new Entities.Shipping
|
||||
@@ -355,7 +375,7 @@ public sealed class OrderService(IDbContextFactory<MidrandBooksDbContext> contex
|
||||
try
|
||||
{
|
||||
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||
|
||||
|
||||
var rowsDeleted = await context.Shippings
|
||||
.Where(s => s.Id == shippingId && s.OrderId == orderId)
|
||||
.ExecuteDeleteAsync(cancellationToken);
|
||||
@@ -398,7 +418,7 @@ public sealed class OrderService(IDbContextFactory<MidrandBooksDbContext> contex
|
||||
{
|
||||
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||
|
||||
if(await context.ShippingProviders.AnyAsync(sp => sp.Type == request.Type, cancellationToken))
|
||||
if (await context.ShippingProviders.AnyAsync(sp => sp.Type == request.Type, cancellationToken))
|
||||
return Result.Fail("Shipping provider with the same type already exists.");
|
||||
|
||||
var shippingProvider = context.ShippingProviders.Add(new Entities.ShippingProvider
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace LiteCharms.Features.MidrandBooks.Payments.Entities;
|
||||
|
||||
[EntityTypeConfiguration<PaymentGatewayConfiguration, PaymentGateway>]
|
||||
public class PaymentGateway : Models.PaymentGateway;
|
||||
public sealed class PaymentGateway : Models.PaymentGateway;
|
||||
|
||||
@@ -7,7 +7,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
namespace LiteCharms.Features.MidrandBooks.Postgres.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Init : Migration
|
||||
public sealed partial class Init : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
namespace LiteCharms.Features.MidrandBooks.Postgres.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddedCategories : Migration
|
||||
public sealed partial class AddedCategories : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
namespace LiteCharms.Features.MidrandBooks.Postgres.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddedProductCategories : Migration
|
||||
public sealed partial class AddedProductCategories : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
namespace LiteCharms.Features.MidrandBooks.Postgres.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddedPaymentObjects : Migration
|
||||
public sealed partial class AddedPaymentObjects : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
namespace LiteCharms.Features.MidrandBooks.Postgres.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class RemovedPassphraseFromPaymentGateway : Migration
|
||||
public sealed partial class RemovedPassphraseFromPaymentGateway : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
namespace LiteCharms.Features.MidrandBooks.Postgres.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddedPaymentGatewayLedger : Migration
|
||||
public sealed partial class AddedPaymentGatewayLedger : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
namespace LiteCharms.Features.MidrandBooks.Postgres.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddedPayfastPaymentIdToPaymentGatewayLedger : Migration
|
||||
public sealed partial class AddedPayfastPaymentIdToPaymentGatewayLedger : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
namespace LiteCharms.Features.MidrandBooks.Postgres.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class OnlyEmailIsMandatoryOnCustomer : Migration
|
||||
public sealed partial class OnlyEmailIsMandatoryOnCustomer : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
<!-- Mediator -->
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Mediator.Abstractions" Version="3.0.2" />
|
||||
<PackageReference Include="Mediator.SourceGenerator" Version="3.0.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
||||
@@ -12,11 +12,7 @@
|
||||
<PackageReference Include="coverlet.collector" Version="10.0.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Mediator.SourceGenerator" Version="3.0.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.6.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace LiteCharms.Features;
|
||||
|
||||
public sealed class CancellationTokenProvider : IDisposable
|
||||
{
|
||||
private readonly CancellationTokenSource source = new();
|
||||
|
||||
public CancellationToken Token => source.Token;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
source.Cancel();
|
||||
source.Dispose();
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,6 @@ using LiteCharms.Features.Api;
|
||||
using LiteCharms.Features.Api.Configuration;
|
||||
using LiteCharms.Features.Api.Sdk;
|
||||
using LiteCharms.Features.Postgres;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace LiteCharms.Features.Extensions;
|
||||
|
||||
@@ -56,9 +54,22 @@ public static class Api
|
||||
|
||||
public static IServiceCollection AddLiteCharmsWebSecurity(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
var certString = configuration["DataProtection:Certificate"] ?? configuration["DataProtection__Certificate"];
|
||||
var certPassword = configuration["DataProtection:Password"] ?? configuration["DataProtection__Password"];
|
||||
|
||||
if (string.IsNullOrEmpty(certString))
|
||||
throw new InvalidOperationException("Data Protection Certificate configuration is missing.");
|
||||
|
||||
var certificate = X509CertificateLoader.LoadPkcs12(Convert.FromBase64String(certString), certPassword);
|
||||
|
||||
services.AddDataProtection().PersistKeysToDbContext<DataProtectionDbContext>()
|
||||
.ProtectKeysWithCertificate(certificate)
|
||||
.SetApplicationName("LiteCharmsApp");
|
||||
|
||||
services.Configure<DataProtectionOptions>(options => options.ApplicationDiscriminator = "LiteCharmsApp");
|
||||
|
||||
services.ConfigureCookieOidcSameSiteSupport();
|
||||
|
||||
var configSection = configuration.GetSection(nameof(LiteCharmsSettings));
|
||||
|
||||
var authOptions = new LiteCharmsSettings();
|
||||
@@ -71,39 +82,48 @@ public static class Api
|
||||
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
|
||||
})
|
||||
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
|
||||
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
|
||||
{
|
||||
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
|
||||
options.Cookie.SameSite = SameSiteMode.Lax;
|
||||
options.Cookie.Name = "LiteCharmsApp.Session";
|
||||
})
|
||||
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
|
||||
{
|
||||
options.Authority = authOptions.Authority;
|
||||
|
||||
options.ClientId = authOptions.ClientId;
|
||||
options.ClientSecret = authOptions.ClientSecret;
|
||||
options.ResponseType = "code";
|
||||
|
||||
|
||||
options.SaveTokens = true;
|
||||
options.GetClaimsFromUserInfoEndpoint = true;
|
||||
|
||||
options.GetClaimsFromUserInfoEndpoint = true;
|
||||
options.CorrelationCookie.SecurePolicy = CookieSecurePolicy.Always;
|
||||
options.CorrelationCookie.SameSite = SameSiteMode.None;
|
||||
|
||||
options.NonceCookie.SecurePolicy = CookieSecurePolicy.Always;
|
||||
options.NonceCookie.SameSite = SameSiteMode.None;
|
||||
|
||||
options.ForwardSignOut = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
|
||||
|
||||
options.Scope.Clear();
|
||||
options.Scope.Add("openid");
|
||||
options.Scope.Add("profile");
|
||||
options.Scope.Add("email");
|
||||
|
||||
|
||||
options.Events = new OpenIdConnectEvents
|
||||
{
|
||||
OnRedirectToIdentityProviderForSignOut = context =>
|
||||
{
|
||||
var idToken = context.ProtocolMessage.IdTokenHint;
|
||||
|
||||
|
||||
if (string.IsNullOrEmpty(idToken))
|
||||
{
|
||||
var tokens = context.Properties.GetTokens();
|
||||
var idTokenItem = tokens.FirstOrDefault(t => string.Equals(t.Name, "id_token", StringComparison.Ordinal));
|
||||
|
||||
|
||||
if (idTokenItem != null) context.ProtocolMessage.IdTokenHint = idTokenItem.Value;
|
||||
}
|
||||
|
||||
|
||||
return Task.CompletedTask;
|
||||
},
|
||||
};
|
||||
@@ -114,6 +134,30 @@ public static class Api
|
||||
return services;
|
||||
}
|
||||
|
||||
private static void ConfigureCookieOidcSameSiteSupport(this IServiceCollection services) =>
|
||||
services.Configure<CookiePolicyOptions>(options =>
|
||||
{
|
||||
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
|
||||
options.OnAppendCookie = cookieContext => CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
|
||||
options.OnDeleteCookie = cookieContext => CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
|
||||
});
|
||||
|
||||
private static void CheckSameSite(HttpContext httpContext, CookieOptions options)
|
||||
{
|
||||
if (options.SameSite == SameSiteMode.None)
|
||||
{
|
||||
bool isSecure = httpContext.Request.IsHttps;
|
||||
|
||||
if (!isSecure && httpContext.Request.Headers.TryGetValue("X-Forwarded-Proto", out var proto))
|
||||
isSecure = string.Equals(proto, "https", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (!isSecure && httpContext.Request.Headers.TryGetValue("Forwarded", out var forwarded))
|
||||
isSecure = forwarded.ToString().Contains("proto=https", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (!isSecure) options.SameSite = SameSiteMode.Unspecified;
|
||||
}
|
||||
}
|
||||
|
||||
public static IServiceCollection AddLiteCharmsApiSecurity(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
var configSection = configuration.GetSection(nameof(LiteCharmsSettings));
|
||||
@@ -197,7 +241,7 @@ public static class Api
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(urls))
|
||||
{
|
||||
string firstUrl = urls.Split(';').FirstOrDefault(s => s.Contains("http://"))!
|
||||
string firstUrl = urls.Split(';').FirstOrDefault(s => s.Contains("http://", StringComparison.InvariantCultureIgnoreCase))!
|
||||
.Replace("0.0.0.0", "localhost")
|
||||
.Replace("*", "localhost")
|
||||
.Replace("+", "localhost");
|
||||
|
||||
@@ -9,7 +9,7 @@ public static class Postgres
|
||||
|
||||
public static IServiceCollection AddDataProtectionDatabase(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
var connectionString = configuration.GetConnectionString(DataProtectionDbConfigName);
|
||||
var connectionString = configuration.GetConnectionString(DataProtectionDbConfigName);
|
||||
|
||||
services.AddPooledDbContextFactory<DataProtectionDbContext>(options =>
|
||||
options.UseNpgsql(connectionString));
|
||||
|
||||
@@ -19,7 +19,7 @@ public static class S3
|
||||
AuthenticationRegion = configuration.GetSection($"{BookshopS3SettingsSection}:Region").Value,
|
||||
ForcePathStyle = true,
|
||||
EndpointDiscoveryEnabled = true,
|
||||
UseHttp = configuration.GetSection($"{BookshopS3SettingsSection}:ServiceUrl").Value!.Contains("http://")
|
||||
UseHttp = configuration.GetSection($"{BookshopS3SettingsSection}:ServiceUrl").Value!.Contains("http://", StringComparison.InvariantCultureIgnoreCase),
|
||||
}));
|
||||
|
||||
services.AddKeyedScoped<IS3Service, BookshopS3Service>(BookshopBucketName);
|
||||
@@ -36,7 +36,7 @@ public static class S3
|
||||
AuthenticationRegion = configuration.GetSection($"{BookshopInvoicesS3SettingsSection}:Region").Value,
|
||||
ForcePathStyle = true,
|
||||
EndpointDiscoveryEnabled = true,
|
||||
UseHttp = configuration.GetSection($"{BookshopS3SettingsSection}:ServiceUrl").Value!.Contains("http://")
|
||||
UseHttp = configuration.GetSection($"{BookshopS3SettingsSection}:ServiceUrl").Value!.Contains("http://", StringComparison.InvariantCultureIgnoreCase),
|
||||
}));
|
||||
|
||||
services.AddKeyedScoped<IS3Service, BookshopInvoicesS3Service>(BookshopInvoicesBucketName);
|
||||
@@ -53,7 +53,7 @@ public static class S3
|
||||
AuthenticationRegion = configuration.GetSection($"{BookshopQuotesS3SettingsSection}:Region").Value,
|
||||
ForcePathStyle = true,
|
||||
EndpointDiscoveryEnabled = true,
|
||||
UseHttp = configuration.GetSection($"{BookshopS3SettingsSection}:ServiceUrl").Value!.Contains("http://")
|
||||
UseHttp = configuration.GetSection($"{BookshopS3SettingsSection}:ServiceUrl").Value!.Contains("http://", StringComparison.InvariantCultureIgnoreCase),
|
||||
}));
|
||||
|
||||
services.AddKeyedScoped<IS3Service, BookshopQuotesS3Service>(BookshopQuotesBucketName);
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace LiteCharms.Features.Extensions;
|
||||
|
||||
public static class TaskCancellation
|
||||
{
|
||||
public static IServiceCollection AddCancellationToken(this IServiceCollection services)
|
||||
{
|
||||
services.AddScoped<CancellationTokenProvider>();
|
||||
services.AddScoped(typeof(CancellationToken),
|
||||
provider => provider.GetRequiredService<CancellationTokenProvider>().Token);
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
@@ -79,7 +79,7 @@
|
||||
<!-- Quartz Scheduler-->
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Hashids.net" Version="1.7.0" />
|
||||
<PackageReference Include="Meziantou.Analyzer" Version="3.0.103">
|
||||
<PackageReference Include="Meziantou.Analyzer" Version="3.0.104">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
@@ -197,6 +197,7 @@
|
||||
<!-- Shared Usings -->
|
||||
<ItemGroup>
|
||||
<Using Include="Microsoft.AspNetCore.DataProtection" />
|
||||
<Using Include="System.Security.Cryptography.X509Certificates" />
|
||||
<Using Include="Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage" />
|
||||
<Using Include="System.Text.Json.Serialization" />
|
||||
<Using Include="System.Reflection" />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace LiteCharms.Features.Postgres;
|
||||
|
||||
public class DataProtectionDbContext(DbContextOptions<DataProtectionDbContext> options) : DbContext(options), IDataProtectionKeyContext
|
||||
public sealed class DataProtectionDbContext(DbContextOptions<DataProtectionDbContext> options) : DbContext(options), IDataProtectionKeyContext
|
||||
{
|
||||
public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace LiteCharms.Features.Postgres;
|
||||
|
||||
public class DataProtectionDbContextFactory : IDesignTimeDbContextFactory<DataProtectionDbContext>
|
||||
public sealed class DataProtectionDbContextFactory : IDesignTimeDbContextFactory<DataProtectionDbContext>
|
||||
{
|
||||
public DataProtectionDbContext CreateDbContext(string[] args)
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
namespace LiteCharms.Features.Postgres.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Init : Migration
|
||||
public sealed partial class Init : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
|
||||
Reference in New Issue
Block a user