使用 TimeProvider 类注入时间
This commit is contained in:
parent
81c8f608dc
commit
c10d9726a2
@ -12,13 +12,13 @@ using System.Text.Encodings.Web;
|
|||||||
|
|
||||||
namespace HelloShop.IdentityService.Authentication;
|
namespace HelloShop.IdentityService.Authentication;
|
||||||
|
|
||||||
public class CustomJwtBearerHandler(IOptionsMonitor<CustomJwtBearerOptions> options, ILoggerFactory logger, UrlEncoder encoder) : SignInAuthenticationHandler<CustomJwtBearerOptions>(options, logger, encoder)
|
public class CustomJwtBearerHandler(IOptionsMonitor<CustomJwtBearerOptions> options, ILoggerFactory logger, UrlEncoder encoder,TimeProvider timeProvider) : SignInAuthenticationHandler<CustomJwtBearerOptions>(options, logger, encoder)
|
||||||
{
|
{
|
||||||
protected override Task<AuthenticateResult> HandleAuthenticateAsync() => throw new NotImplementedException();
|
protected override Task<AuthenticateResult> HandleAuthenticateAsync() => throw new NotImplementedException();
|
||||||
|
|
||||||
protected override async Task HandleSignInAsync(ClaimsPrincipal user, AuthenticationProperties? properties)
|
protected override async Task HandleSignInAsync(ClaimsPrincipal user, AuthenticationProperties? properties)
|
||||||
{
|
{
|
||||||
var utcNow = TimeProvider.GetUtcNow();
|
var utcNow =timeProvider.GetUtcNow();
|
||||||
|
|
||||||
JwtSecurityTokenHandler tokenHandler = new();
|
JwtSecurityTokenHandler tokenHandler = new();
|
||||||
|
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
// Copyright (c) HelloShop Corporation. All rights reserved.
|
|
||||||
// See the license file in the project root for more information.
|
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace HelloShop.IdentityService.Controllers;
|
|
||||||
|
|
||||||
[ApiController]
|
|
||||||
[Route("[controller]")]
|
|
||||||
public class WeatherForecastController : ControllerBase
|
|
||||||
{
|
|
||||||
private static readonly string[] Summaries = new[]
|
|
||||||
{
|
|
||||||
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
|
|
||||||
};
|
|
||||||
|
|
||||||
private readonly ILogger<WeatherForecastController> _logger;
|
|
||||||
|
|
||||||
public WeatherForecastController(ILogger<WeatherForecastController> logger)
|
|
||||||
{
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet(Name = "GetWeatherForecast")]
|
|
||||||
public IEnumerable<WeatherForecast> Get()
|
|
||||||
{
|
|
||||||
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
|
|
||||||
{
|
|
||||||
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
|
|
||||||
TemperatureC = Random.Shared.Next(-20, 55),
|
|
||||||
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
|
|
||||||
})
|
|
||||||
.ToArray();
|
|
||||||
}
|
|
||||||
}
|
|
@ -61,6 +61,7 @@ builder.Services.AddPermissionDefinitions();
|
|||||||
builder.Services.AddAuthorization().AddDistributedMemoryCache().AddHttpClient().AddHttpContextAccessor().AddTransient<IPermissionChecker, LocalPermissionChecker>().AddCustomAuthorization();
|
builder.Services.AddAuthorization().AddDistributedMemoryCache().AddHttpClient().AddHttpContextAccessor().AddTransient<IPermissionChecker, LocalPermissionChecker>().AddCustomAuthorization();
|
||||||
builder.Services.AddModelMapper().AddModelValidator();
|
builder.Services.AddModelMapper().AddModelValidator();
|
||||||
builder.Services.AddCustomLocalization();
|
builder.Services.AddCustomLocalization();
|
||||||
|
builder.Services.AddSingleton(TimeProvider.System);
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
// Copyright (c) HelloShop Corporation. All rights reserved.
|
|
||||||
// See the license file in the project root for more information.
|
|
||||||
|
|
||||||
namespace HelloShop.IdentityService;
|
|
||||||
|
|
||||||
public class WeatherForecast
|
|
||||||
{
|
|
||||||
public DateOnly Date { get; set; }
|
|
||||||
|
|
||||||
public int TemperatureC { get; set; }
|
|
||||||
|
|
||||||
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
|
||||||
|
|
||||||
public string? Summary { get; set; }
|
|
||||||
}
|
|
@ -69,6 +69,8 @@ namespace HelloShop.OrderingService.Extensions
|
|||||||
builder.Services.AddTransient<IDistributedEventService, DistributedEventService<OrderingServiceDbContext>>();
|
builder.Services.AddTransient<IDistributedEventService, DistributedEventService<OrderingServiceDbContext>>();
|
||||||
|
|
||||||
builder.Services.AddOpenApi();
|
builder.Services.AddOpenApi();
|
||||||
|
|
||||||
|
builder.Services.AddSingleton(TimeProvider.System);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static WebApplication MapApplicationEndpoints(this WebApplication app)
|
public static WebApplication MapApplicationEndpoints(this WebApplication app)
|
||||||
|
@ -8,7 +8,7 @@ namespace HelloShop.OrderingService.Validations.Commands
|
|||||||
{
|
{
|
||||||
public class CreateOrderCommandValidator : AbstractValidator<CreateOrderCommand>
|
public class CreateOrderCommandValidator : AbstractValidator<CreateOrderCommand>
|
||||||
{
|
{
|
||||||
public CreateOrderCommandValidator()
|
public CreateOrderCommandValidator(TimeProvider timeProvider)
|
||||||
{
|
{
|
||||||
RuleFor(x => x.UserId).GreaterThan(0);
|
RuleFor(x => x.UserId).GreaterThan(0);
|
||||||
RuleFor(x => x.UserName).NotNull().NotEmpty().Length(1, 16);
|
RuleFor(x => x.UserName).NotNull().NotEmpty().Length(1, 16);
|
||||||
@ -23,7 +23,7 @@ namespace HelloShop.OrderingService.Validations.Commands
|
|||||||
RuleFor(x => x.CardNumber).NotNull().NotEmpty().Length(16).Must(x => x.All(char.IsNumber));
|
RuleFor(x => x.CardNumber).NotNull().NotEmpty().Length(16).Must(x => x.All(char.IsNumber));
|
||||||
RuleFor(x => x.CardHolderName).NotNull().NotEmpty().Length(1, 8);
|
RuleFor(x => x.CardHolderName).NotNull().NotEmpty().Length(1, 8);
|
||||||
RuleFor(x => x.CardSecurityNumber).NotNull().NotEmpty().Length(6).Must(x => x.All(char.IsNumber));
|
RuleFor(x => x.CardSecurityNumber).NotNull().NotEmpty().Length(6).Must(x => x.All(char.IsNumber));
|
||||||
RuleFor(x => x.CardExpiration).Must(x => x.HasValue && x.Value > DateTimeOffset.Now);
|
RuleFor(x => x.CardExpiration).Must(x => x.HasValue && x.Value > timeProvider.GetUtcNow());
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BasketListItemValidator : AbstractValidator<CreateOrderCommand.CreateOrderCommandItem>
|
public class BasketListItemValidator : AbstractValidator<CreateOrderCommand.CreateOrderCommandItem>
|
||||||
|
@ -8,7 +8,7 @@ namespace HelloShop.OrderingService.Validations.Models
|
|||||||
{
|
{
|
||||||
public class CreateOrderRequestValidator : AbstractValidator<CreateOrderRequest>
|
public class CreateOrderRequestValidator : AbstractValidator<CreateOrderRequest>
|
||||||
{
|
{
|
||||||
public CreateOrderRequestValidator()
|
public CreateOrderRequestValidator(TimeProvider timeProvider)
|
||||||
{
|
{
|
||||||
RuleFor(x => x.Items).NotNull().NotEmpty();
|
RuleFor(x => x.Items).NotNull().NotEmpty();
|
||||||
RuleForEach(x => x.Items).SetValidator(new BasketListItemValidator());
|
RuleForEach(x => x.Items).SetValidator(new BasketListItemValidator());
|
||||||
@ -21,7 +21,7 @@ namespace HelloShop.OrderingService.Validations.Models
|
|||||||
RuleFor(x => x.CardNumber).NotNull().NotEmpty().Length(16).Must(x => x.All(char.IsNumber));
|
RuleFor(x => x.CardNumber).NotNull().NotEmpty().Length(16).Must(x => x.All(char.IsNumber));
|
||||||
RuleFor(x => x.CardHolderName).NotNull().NotEmpty().Length(1, 8);
|
RuleFor(x => x.CardHolderName).NotNull().NotEmpty().Length(1, 8);
|
||||||
RuleFor(x => x.CardSecurityNumber).NotNull().NotEmpty().Length(6).Must(x => x.All(char.IsNumber));
|
RuleFor(x => x.CardSecurityNumber).NotNull().NotEmpty().Length(6).Must(x => x.All(char.IsNumber));
|
||||||
RuleFor(x => x.CardExpiration).Must(x => x.HasValue && x.Value > DateTimeOffset.Now);
|
RuleFor(x => x.CardExpiration).Must(x => x.HasValue && x.Value > timeProvider.GetLocalNow());
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BasketListItemValidator : AbstractValidator<BasketItem>
|
public class BasketListItemValidator : AbstractValidator<BasketItem>
|
||||||
|
@ -10,7 +10,7 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
|
|
||||||
namespace HelloShop.OrderingService.Workers
|
namespace HelloShop.OrderingService.Workers
|
||||||
{
|
{
|
||||||
public class GracePeriodWorker(IServiceScopeFactory serviceScopeFactory, ILogger<GracePeriodWorker> logger) : BackgroundService
|
public class GracePeriodWorker(IServiceScopeFactory serviceScopeFactory, ILogger<GracePeriodWorker> logger,TimeProvider timeProvider) : BackgroundService
|
||||||
{
|
{
|
||||||
protected async override Task ExecuteAsync(CancellationToken stoppingToken)
|
protected async override Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
{
|
{
|
||||||
@ -25,7 +25,7 @@ namespace HelloShop.OrderingService.Workers
|
|||||||
var dbContext = scope.ServiceProvider.GetRequiredService<OrderingServiceDbContext>();
|
var dbContext = scope.ServiceProvider.GetRequiredService<OrderingServiceDbContext>();
|
||||||
var distributedEventBus = scope.ServiceProvider.GetRequiredService<IDistributedEventBus>();
|
var distributedEventBus = scope.ServiceProvider.GetRequiredService<IDistributedEventBus>();
|
||||||
|
|
||||||
DateTimeOffset dateTimeOffset = DateTimeOffset.UtcNow.AddMinutes(-1);
|
DateTimeOffset dateTimeOffset = timeProvider.GetUtcNow().AddMinutes(-1);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -43,6 +43,7 @@ builder.Services.AddLocalization().AddPermissionDefinitions();
|
|||||||
builder.Services.AddAuthorization().AddRemotePermissionChecker().AddCustomAuthorization();
|
builder.Services.AddAuthorization().AddRemotePermissionChecker().AddCustomAuthorization();
|
||||||
builder.AddDaprDistributedEventBus().AddSubscriptionFromAssembly();
|
builder.AddDaprDistributedEventBus().AddSubscriptionFromAssembly();
|
||||||
builder.Services.AddSingleton<IDistributedLock, DaprDistributedLock>();
|
builder.Services.AddSingleton<IDistributedLock, DaprDistributedLock>();
|
||||||
|
builder.Services.AddSingleton(TimeProvider.System);
|
||||||
// End addd extensions services to the container.
|
// End addd extensions services to the container.
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
@ -8,7 +8,7 @@ using System.Security.Claims;
|
|||||||
|
|
||||||
namespace HelloShop.ServiceDefaults.Authorization;
|
namespace HelloShop.ServiceDefaults.Authorization;
|
||||||
|
|
||||||
public abstract class PermissionChecker(IHttpContextAccessor httpContextAccessor, IDistributedCache distributedCache) : IPermissionChecker
|
public abstract class PermissionChecker(IHttpContextAccessor httpContextAccessor, IDistributedCache distributedCache,TimeProvider timeProvider) : IPermissionChecker
|
||||||
{
|
{
|
||||||
protected HttpContext HttpContext { get; init; } = httpContextAccessor.HttpContext ?? throw new InvalidOperationException();
|
protected HttpContext HttpContext { get; init; } = httpContextAccessor.HttpContext ?? throw new InvalidOperationException();
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ public abstract class PermissionChecker(IHttpContextAccessor httpContextAccessor
|
|||||||
|
|
||||||
await distributedCache.SetObjectAsync(cacheKey, new PermissionGrantCacheItem(isGranted), new DistributedCacheEntryOptions
|
await distributedCache.SetObjectAsync(cacheKey, new PermissionGrantCacheItem(isGranted), new DistributedCacheEntryOptions
|
||||||
{
|
{
|
||||||
AbsoluteExpiration = DateTimeOffset.Now
|
AbsoluteExpiration = timeProvider.GetUtcNow()
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isGranted)
|
if (isGranted)
|
||||||
|
@ -11,7 +11,7 @@ namespace HelloShop.ServiceDefaults.DistributedEvents.Abstractions
|
|||||||
public DistributedEvent()
|
public DistributedEvent()
|
||||||
{
|
{
|
||||||
Id = Guid.NewGuid();
|
Id = Guid.NewGuid();
|
||||||
CreationTime = DateTimeOffset.UtcNow;
|
CreationTime = TimeProvider.System.GetUtcNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.3" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.3" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.3" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.3" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.TimeProvider.Testing" Version="9.3.0" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
|
||||||
<PackageReference Include="Moq" Version="4.20.72" />
|
<PackageReference Include="Moq" Version="4.20.72" />
|
||||||
<PackageReference Include="xunit" Version="2.9.3" />
|
<PackageReference Include="xunit" Version="2.9.3" />
|
||||||
|
@ -9,6 +9,7 @@ using HelloShop.ProductService.Infrastructure;
|
|||||||
using HelloShop.ProductService.Models.Products;
|
using HelloShop.ProductService.Models.Products;
|
||||||
using HelloShop.ProductService.UnitTests.Helpers;
|
using HelloShop.ProductService.UnitTests.Helpers;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Time.Testing;
|
||||||
|
|
||||||
namespace HelloShop.ProductService.UnitTests
|
namespace HelloShop.ProductService.UnitTests
|
||||||
{
|
{
|
||||||
@ -60,5 +61,16 @@ namespace HelloShop.ProductService.UnitTests
|
|||||||
Assert.Equal(productName, result?.Name);
|
Assert.Equal(productName, result?.Name);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UseTimeProviderTestService()
|
||||||
|
{
|
||||||
|
FakeTimeProvider fakeTimeProvider = new();
|
||||||
|
fakeTimeProvider.SetUtcNow(fakeTimeProvider.GetUtcNow().AddDays(1));
|
||||||
|
|
||||||
|
Assert.Equal(DateTime.UtcNow.AddHours(1), fakeTimeProvider.GetUtcNow());
|
||||||
|
|
||||||
|
await Task.CompletedTask;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user