Compare commits
276 Commits
a01e6e5b16
...
feat/secur
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ad8d15314f | ||
|
|
f1efbae6a4 | ||
|
|
051567aa0a | ||
|
|
287871ddc6 | ||
|
|
a0ad8d732d | ||
|
|
3ad08e2a86 | ||
|
|
b90a52412c | ||
|
|
39091ff5cf | ||
|
|
22040cf1e7 | ||
|
|
af4b7d5438 | ||
|
|
211064d44e | ||
|
|
66e3c771dd | ||
|
|
97c4f7bf8f | ||
|
|
5981ba7a8d | ||
|
|
21e164ceb7 | ||
|
|
1875bf46fa | ||
|
|
7f9459f6cf | ||
|
|
079f0c69c7 | ||
|
|
d98b3f2867 | ||
|
|
3761c13dba | ||
|
|
8acbbaeb2e | ||
|
|
60e1ec78b3 | ||
|
|
e623575fe8 | ||
|
|
60ae8de550 | ||
|
|
87ad45f42a | ||
|
|
2557525f06 | ||
|
|
7a938f0379 | ||
|
|
9f0facc487 | ||
|
|
608d266d1c | ||
|
|
34e14fd2f5 | ||
|
|
dc45cf2c08 | ||
|
|
09a31b5a3d | ||
|
|
b5cecac745 | ||
|
|
0f4b5430a3 | ||
|
|
7f2d2dadfa | ||
|
|
ac0b6f739b | ||
|
|
d9d61368e3 | ||
|
|
e8c98115b6 | ||
|
|
09dae1b1ac | ||
|
|
9aafc9e467 | ||
|
|
4ce738957d | ||
|
|
5e1bf16b6d | ||
|
|
4f96d271f3 | ||
|
|
14485af448 | ||
|
|
c27e21a702 | ||
|
|
4874079b69 | ||
|
|
15e909064f | ||
|
|
d17c5ca6cd | ||
|
|
592b949f57 | ||
|
|
8850ac4ac9 | ||
|
|
8ccf6f31ae | ||
|
|
9875d023e3 | ||
|
|
62afba7c23 | ||
|
|
1d4882cfbc | ||
|
|
275b9ec858 | ||
|
|
2cf0eb3977 | ||
|
|
4ab5393deb | ||
|
|
a2dc59d5ef | ||
|
|
ed041bf7cb | ||
|
|
c70327e7f4 | ||
|
|
0a3ce89c0d | ||
|
|
389d64c25d | ||
|
|
a3931414e3 | ||
|
|
0dd897625a | ||
|
|
351a6732cf | ||
|
|
5a1808c6a6 | ||
|
|
50c42e9cdd | ||
|
|
ec126be2aa | ||
|
|
9953bbd2ef | ||
|
|
dbecfa92f4 | ||
|
|
e007f15bce | ||
|
|
79dffef528 | ||
|
|
af478e974c | ||
|
|
435c91955c | ||
|
|
4142d2d948 | ||
|
|
06260e0edb | ||
|
|
2d675a16ad | ||
|
|
5469b20e4f | ||
|
|
6f5b4efefb | ||
|
|
b6b12c7702 | ||
|
|
ce716d2bab | ||
|
|
bf672d8b8c | ||
|
|
ed29c9f990 | ||
|
|
66ed34b664 | ||
|
|
d7b4c382cd | ||
|
|
4f6ca3524a | ||
|
|
bd1ae4246d | ||
|
|
d92475c230 | ||
|
|
15705cccc4 | ||
|
|
a8403087f6 | ||
|
|
0235c83075 | ||
|
|
63aeba982f | ||
|
|
514495fc8d | ||
|
|
9752fb14ec | ||
|
|
b3629661a1 | ||
|
|
f38bad8531 | ||
|
|
154478c318 | ||
|
|
155eb563d1 | ||
|
|
4aacc3f650 | ||
|
|
f40c86ed63 | ||
|
|
b32f0df125 | ||
|
|
324a5bdb1e | ||
|
|
e0a6787a87 | ||
|
|
c6a4038eab | ||
|
|
58c8520c08 | ||
|
|
eced1a5afc | ||
|
|
7da93c6719 | ||
|
|
6a92466490 | ||
|
|
5d9d756b91 | ||
|
|
f14aaa75e1 | ||
|
|
249f5a0ae5 | ||
|
|
30177cf0c7 | ||
|
|
68ef0a7537 | ||
|
|
fe2ee78d14 | ||
|
|
53e6f37a09 | ||
|
|
7ec85b4e30 | ||
|
|
a9ebc406f3 | ||
|
|
d013d3edfa | ||
|
|
f267fe955b | ||
|
|
644283cf8f | ||
|
|
82aa8d1143 | ||
|
|
7459f05748 | ||
|
|
36f75d003a | ||
|
|
76ce64691a | ||
|
|
7c03282066 | ||
|
|
7ae95b729f | ||
|
|
9ee8a51664 | ||
|
|
b1d1a898b8 | ||
|
|
4ed3e79565 | ||
|
|
8d9de4502e | ||
|
|
7dd91c73c4 | ||
|
|
988d1e2b16 | ||
|
|
4e0e907313 | ||
|
|
0bfec426d4 | ||
|
|
08ffe821ff | ||
|
|
fa5d0f1b26 | ||
|
|
38bd23d012 | ||
|
|
50e2581727 | ||
|
|
5c09d7775b | ||
|
|
dbfee49dee | ||
|
|
0c6c84852d | ||
|
|
3f61b5064c | ||
|
|
f79d2e2352 | ||
|
|
201da81aa5 | ||
|
|
bea57a25e8 | ||
|
|
0ff89b4906 | ||
|
|
600d17ef40 | ||
|
|
16565eca4d | ||
|
|
8787c04917 | ||
|
|
b3568216a0 | ||
|
|
6f520732dd | ||
|
|
8003cffb9b | ||
|
|
b02f93b38d | ||
|
|
2f0c6a905a | ||
|
|
baf1f5e045 | ||
|
|
b8a4a1f2b5 | ||
|
|
a69f610ef4 | ||
|
|
016d8bdcf2 | ||
|
|
738005f5dc | ||
|
|
c96af25e23 | ||
|
|
35e2fef046 | ||
|
|
b8fb45d4a3 | ||
|
|
fa60147507 | ||
|
|
e9d408a717 | ||
|
|
5fd3fa2fc6 | ||
|
|
0d5bcedc01 | ||
|
|
2e68a37944 | ||
|
|
8076efb934 | ||
|
|
c38f7dcf72 | ||
|
|
6e4942c885 | ||
|
|
d0dfd834b0 | ||
|
|
aa9951f242 | ||
|
|
506685a0b5 | ||
|
|
c9548238bb | ||
|
|
3ffdd49a47 | ||
|
|
609cd29dc5 | ||
|
|
cc3d1f58d3 | ||
|
|
c03f39c1a9 | ||
|
|
750f7bc20c | ||
|
|
65989b23b3 | ||
|
|
c895d2df0e | ||
|
|
0c451cb834 | ||
|
|
9396f48f46 | ||
|
|
1a941b4728 | ||
|
|
c6942164e2 | ||
|
|
343560ed62 | ||
|
|
6873bac8a1 | ||
|
|
09406ca505 | ||
|
|
3aa5ad782f | ||
|
|
5991444efd | ||
|
|
f720ea9cd6 | ||
|
|
a4b96c2f3e | ||
|
|
65c64a3f9a | ||
|
|
1d600aa453 | ||
|
|
816d5835f1 | ||
|
|
4a64a31d47 | ||
|
|
e9b2ba788f | ||
|
|
e53813500a | ||
|
|
25e3855de2 | ||
|
|
dd3d6e70cc | ||
|
|
02a87309df | ||
|
|
0f7bdc9d0e | ||
|
|
f9df2fb29e | ||
|
|
ef7da0e52c | ||
|
|
f602a842be | ||
|
|
52a7664e57 | ||
|
|
ea3d1312b8 | ||
|
|
3b8b315fea | ||
|
|
c65eefb954 | ||
|
|
997fd533ac | ||
|
|
bcfb5a8a70 | ||
|
|
049e9977f4 | ||
|
|
0334fc4cdf | ||
|
|
0c2334cefb | ||
|
|
dd7f1c1ea0 | ||
|
|
4bb242a4cc | ||
|
|
b577067379 | ||
|
|
bd4d4856ea | ||
|
|
c3a12ba5b7 | ||
|
|
478bf13a4a | ||
|
|
d8849f48da | ||
|
|
c466c553dc | ||
|
|
48afa6b433 | ||
|
|
e44b2895c9 | ||
|
|
85e5fc4018 | ||
|
|
70ccec9fef | ||
|
|
f7193594b1 | ||
|
|
9c7319634a | ||
|
|
3becb208ec | ||
|
|
1b00f9afa2 | ||
|
|
b58d4aed2f | ||
|
|
5adc67edf2 | ||
|
|
0ff0de8159 | ||
|
|
49b49271f3 | ||
|
|
5c5a6bd181 | ||
|
|
6ab1777f7c | ||
|
|
103ddf5c2e | ||
|
|
f9c94e8464 | ||
|
|
cdb0009e7c | ||
|
|
5010224500 | ||
|
|
1ebdd7e5bb | ||
|
|
0e0513e640 | ||
|
|
683b95c205 | ||
|
|
f28b43cc06 | ||
|
|
777a8a73ac | ||
|
|
77fc06991b | ||
|
|
eeb50e837d | ||
|
|
1b210714fd | ||
|
|
806bc01c17 | ||
|
|
0169097671 | ||
|
|
90c73237eb | ||
|
|
2a9c9551b8 | ||
|
|
a39728dff5 | ||
|
|
7048f385ef | ||
|
|
cb9c5746b0 | ||
|
|
ed36015d1e | ||
|
|
6ce4a08c53 | ||
|
|
4c379c2d4d | ||
|
|
fee43c00ca | ||
|
|
ee3060158e | ||
|
|
4e615d7e39 | ||
|
|
d1fea581d7 | ||
|
|
26a68cd477 | ||
|
|
eccf2b32ce | ||
|
|
6ff0d0a876 | ||
|
|
0bb779b7b6 | ||
|
|
51ebf3fa67 | ||
|
|
8cc6fd95f7 | ||
|
|
c5b422921b | ||
|
|
7b571e4d86 | ||
|
|
c39b554165 | ||
|
|
489ca67203 | ||
|
|
0804ea1418 | ||
|
|
84dbca97d5 | ||
|
|
8c350db146 | ||
|
|
471dace359 |
3
.gitignore
vendored
@@ -408,3 +408,6 @@ FodyWeavers.xsd
|
|||||||
/DigitalData.Core.ConsoleApp/DigitalData.Core.ConsoleApp.csproj
|
/DigitalData.Core.ConsoleApp/DigitalData.Core.ConsoleApp.csproj
|
||||||
/DigitalData.Core.ConsoleApp/Program.cs
|
/DigitalData.Core.ConsoleApp/Program.cs
|
||||||
/DigitalData.Core.ConsoleApp/FooHttpOptions.cs
|
/DigitalData.Core.ConsoleApp/FooHttpOptions.cs
|
||||||
|
/DigitalData.Core.Tests/obj/
|
||||||
|
/DigitalData.Core.Terminal
|
||||||
|
/DigitalData.Core.Tests.API
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1020 KiB |
@@ -7,7 +7,7 @@ namespace DigitalData.Core.API
|
|||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
public class BasicCRUDControllerBase<TCRUDService, TDto, TEntity, TId> : CRUDControllerBase<TCRUDService, TDto, TDto, TDto, TEntity, TId>
|
public class BasicCRUDControllerBase<TCRUDService, TDto, TEntity, TId> : CRUDControllerBase<TCRUDService, TDto, TDto, TDto, TEntity, TId>
|
||||||
where TCRUDService : ICRUDService<TDto, TDto, TDto, TEntity, TId>
|
where TCRUDService : ICRUDService<TDto, TDto, TEntity, TId>
|
||||||
where TDto : class, IUnique<TId>
|
where TDto : class, IUnique<TId>
|
||||||
where TEntity : class, IUnique<TId>
|
where TEntity : class, IUnique<TId>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,13 +11,12 @@ namespace DigitalData.Core.API
|
|||||||
/// <typeparam name="TCRUDService">The derived CRUD service type implementing ICRUDService<TCreateDto, TReadDto, TUpdateDto, TEntity, TId>.</typeparam>
|
/// <typeparam name="TCRUDService">The derived CRUD service type implementing ICRUDService<TCreateDto, TReadDto, TUpdateDto, TEntity, TId>.</typeparam>
|
||||||
/// <typeparam name="TCreateDto">The Data Transfer Object type for create operations.</typeparam>
|
/// <typeparam name="TCreateDto">The Data Transfer Object type for create operations.</typeparam>
|
||||||
/// <typeparam name="TReadDto">The Data Transfer Object type for read operations.</typeparam>
|
/// <typeparam name="TReadDto">The Data Transfer Object type for read operations.</typeparam>
|
||||||
/// <typeparam name="TUpdateDto">The Data Transfer Object type for update operations.</typeparam>
|
|
||||||
/// <typeparam name="TEntity">The entity type CRUD operations will be performed on.</typeparam>
|
/// <typeparam name="TEntity">The entity type CRUD operations will be performed on.</typeparam>
|
||||||
/// <typeparam name="TId">The type of the entity's identifier.</typeparam>
|
/// <typeparam name="TId">The type of the entity's identifier.</typeparam>
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
public class CRUDControllerBase<TCRUDService, TCreateDto, TReadDto, TUpdateDto, TEntity, TId> : ControllerBase
|
public class CRUDControllerBase<TCRUDService, TCreateDto, TReadDto, TUpdateDto, TEntity, TId> : ControllerBase
|
||||||
where TCRUDService : ICRUDService<TCreateDto, TReadDto, TUpdateDto, TEntity, TId>
|
where TCRUDService : ICRUDService<TCreateDto, TReadDto, TEntity, TId>
|
||||||
where TCreateDto : class
|
where TCreateDto : class
|
||||||
where TReadDto : class
|
where TReadDto : class
|
||||||
where TUpdateDto : class, IUnique<TId>
|
where TUpdateDto : class, IUnique<TId>
|
||||||
|
|||||||
@@ -12,13 +12,12 @@ namespace DigitalData.Core.API
|
|||||||
/// <typeparam name="TCRUDService">The derived CRUD service type implementing ICRUDService<TCreateDto, TReadDto, TUpdateDto, TEntity, TId>.</typeparam>
|
/// <typeparam name="TCRUDService">The derived CRUD service type implementing ICRUDService<TCreateDto, TReadDto, TUpdateDto, TEntity, TId>.</typeparam>
|
||||||
/// <typeparam name="TCreateDto">The Data Transfer Object type for create operations.</typeparam>
|
/// <typeparam name="TCreateDto">The Data Transfer Object type for create operations.</typeparam>
|
||||||
/// <typeparam name="TReadDto">The Data Transfer Object type for read operations.</typeparam>
|
/// <typeparam name="TReadDto">The Data Transfer Object type for read operations.</typeparam>
|
||||||
/// <typeparam name="TUpdateDto">The Data Transfer Object type for update operations.</typeparam>
|
|
||||||
/// <typeparam name="TEntity">The entity type CRUD operations will be performed on.</typeparam>
|
/// <typeparam name="TEntity">The entity type CRUD operations will be performed on.</typeparam>
|
||||||
/// <typeparam name="TId">The type of the entity's identifier.</typeparam>
|
/// <typeparam name="TId">The type of the entity's identifier.</typeparam>
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
public class CRUDControllerBaseWithErrorHandling<TCRUDService, TCreateDto, TReadDto, TUpdateDto, TEntity, TId> : ControllerBase
|
public class CRUDControllerBaseWithErrorHandling<TCRUDService, TCreateDto, TReadDto, TUpdateDto, TEntity, TId> : ControllerBase
|
||||||
where TCRUDService : ICRUDService<TCreateDto, TReadDto, TUpdateDto, TEntity, TId>
|
where TCRUDService : ICRUDService<TCreateDto, TReadDto, TEntity, TId>
|
||||||
where TCreateDto : class
|
where TCreateDto : class
|
||||||
where TReadDto : class
|
where TReadDto : class
|
||||||
where TUpdateDto : class, IUnique<TId>
|
where TUpdateDto : class, IUnique<TId>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace DigitalData.Core.API
|
|||||||
/// <param name="index">The key in the ViewData dictionary where the value will be stored.</param>
|
/// <param name="index">The key in the ViewData dictionary where the value will be stored.</param>
|
||||||
/// <param name="value">The value to be stored in the ViewData dictionary.</param>
|
/// <param name="value">The value to be stored in the ViewData dictionary.</param>
|
||||||
/// <returns>The same ViewResult object with updated ViewData, allowing for additional chained operations.</returns>
|
/// <returns>The same ViewResult object with updated ViewData, allowing for additional chained operations.</returns>
|
||||||
public static ViewResult WithData(this ViewResult viewResult, string index, object value)
|
public static ViewResult WithData(this ViewResult viewResult, string index, object? value)
|
||||||
{
|
{
|
||||||
viewResult.ViewData[index] = value;
|
viewResult.ViewData[index] = value;
|
||||||
return viewResult;
|
return viewResult;
|
||||||
|
|||||||
@@ -1,23 +1,32 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
|
||||||
<IsPackable>true</IsPackable>
|
<IsPackable>true</IsPackable>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<Description>This package provides a comprehensive set of API controllers and related utilities for the DigitalData.Core library. It includes generic CRUD controllers, localization extensions, middleware for security policies, and application model conventions.</Description>
|
<Description>This package provides a comprehensive set of API controllers and related utilities for the DigitalData.Core library. It includes generic CRUD controllers, localization extensions, middleware for security policies, and application model conventions.</Description>
|
||||||
<PackageId>DigitalData.Core.API</PackageId>
|
<PackageId>DigitalData.Core.API</PackageId>
|
||||||
<Version>2.0.0.0</Version>
|
<Version>2.1.1</Version>
|
||||||
<Authors>Digital Data GmbH</Authors>
|
<Authors>Digital Data GmbH</Authors>
|
||||||
<Company>Digital Data GmbH</Company>
|
<Company>Digital Data GmbH</Company>
|
||||||
<Product>DigitalData.Core.API</Product>
|
<Product>DigitalData.Core.API</Product>
|
||||||
<Copyright>Copyright 2024</Copyright>
|
<Copyright>Copyright 2024</Copyright>
|
||||||
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
|
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
|
||||||
<PackageTags>digital data core api</PackageTags>
|
<PackageTags>digital data core api</PackageTags>
|
||||||
<PackageIcon>Assets\icon.png</PackageIcon>
|
<PackageIcon>core_icon.png</PackageIcon>
|
||||||
|
<AssemblyVersion>2.1.1</AssemblyVersion>
|
||||||
|
<FileVersion>2.1.1</FileVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="..\..\nuget-package-icons\core_icon.png">
|
||||||
|
<Pack>True</Pack>
|
||||||
|
<PackagePath>\</PackagePath>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace DigitalData.Core.Abstractions.Application
|
|||||||
/// This interface is useful for entities that do not require different DTOs for different operations,
|
/// This interface is useful for entities that do not require different DTOs for different operations,
|
||||||
/// allowing for a more concise and maintainable codebase when implementing services for such entities.
|
/// allowing for a more concise and maintainable codebase when implementing services for such entities.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public interface IBasicCRUDService<TDto, TEntity, TId> : ICRUDService<TDto, TDto, TDto, TEntity, TId>
|
public interface IBasicCRUDService<TDto, TEntity, TId> : ICRUDService<TDto, TDto, TEntity, TId>
|
||||||
where TDto : class, IUnique<TId> where TEntity : class, IUnique<TId>
|
where TDto : class, IUnique<TId> where TEntity : class, IUnique<TId>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
namespace DigitalData.Core.Abstractions.Application
|
namespace DigitalData.Core.Abstractions.Application
|
||||||
{
|
{
|
||||||
public interface ICRUDService<TCreateDto, TReadDto, TUpdateDto, TEntity, TId> : IReadService<TReadDto, TEntity, TId>
|
public interface ICRUDService<TCreateDto, TReadDto, TEntity, TId> : IReadService<TReadDto, TEntity, TId>
|
||||||
where TCreateDto : class where TReadDto : class where TUpdateDto : IUnique<TId> where TEntity : class, IUnique<TId>
|
where TCreateDto : class where TReadDto : class where TEntity : class, IUnique<TId>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Asynchronously creates a new entity based on the provided <paramref name="createDto"/> and returns the identifier of the created entity wrapped in a <see cref="DataResult{TId}"/>.
|
/// Asynchronously creates a new entity based on the provided <paramref name="createDto"/> and returns the identifier of the created entity wrapped in a <see cref="DataResult{TId}"/>.
|
||||||
@@ -20,6 +20,6 @@ namespace DigitalData.Core.Abstractions.Application
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="updateDto">The updateDTO with updated values for the entity.</param>
|
/// <param name="updateDto">The updateDTO with updated values for the entity.</param>
|
||||||
/// <returns>An Result indicating the outcome of the update operation, with an appropriate message.</returns>
|
/// <returns>An Result indicating the outcome of the update operation, with an appropriate message.</returns>
|
||||||
Task<Result> UpdateAsync(TUpdateDto updateDto);
|
Task<Result> UpdateAsync<TUpdateDto>(TUpdateDto updateDto) where TUpdateDto : IUnique<TId>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 1020 KiB |
@@ -4,15 +4,17 @@ namespace DigitalData.Core.Abstractions.Client
|
|||||||
{
|
{
|
||||||
public interface IBaseHttpClientService
|
public interface IBaseHttpClientService
|
||||||
{
|
{
|
||||||
public string Uri { get; init; }
|
CookieCollection GetCookies(string path = "");
|
||||||
|
|
||||||
public CookieCollection GetCookies(string route = "");
|
|
||||||
|
|
||||||
Task<HttpResponseMessage> FetchAsync(
|
Task<HttpResponseMessage> FetchAsync(
|
||||||
string route = "",
|
string? scheme = null,
|
||||||
|
int? port = null,
|
||||||
|
string path = "",
|
||||||
|
IEnumerable<KeyValuePair<string, object?>>? queryParams = null,
|
||||||
HttpMethod? method = null,
|
HttpMethod? method = null,
|
||||||
HttpContent? body = null,
|
HttpContent? body = null,
|
||||||
Dictionary<string, string>? form = null,
|
IEnumerable<KeyValuePair<string, object>>? form = null,
|
||||||
|
IEnumerable<KeyValuePair<string, object>>? headers = null,
|
||||||
bool sendWithCookie = true,
|
bool sendWithCookie = true,
|
||||||
bool saveCookie = true
|
bool saveCookie = true
|
||||||
);
|
);
|
||||||
|
|||||||
13
DigitalData.Core.Abstractions/Client/IHttpClientOptions.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
namespace DigitalData.Core.Abstractions.Client
|
||||||
|
{
|
||||||
|
public interface IHttpClientOptions
|
||||||
|
{
|
||||||
|
string Uri { get; init; }
|
||||||
|
|
||||||
|
string? Path { get; init; }
|
||||||
|
|
||||||
|
Dictionary<string, object>? Headers { get; init; }
|
||||||
|
|
||||||
|
Dictionary<string, object?>? QueryParams { get; init; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace DigitalData.Core.Abstractions.Client
|
namespace DigitalData.Core.Abstractions.Client
|
||||||
{
|
{
|
||||||
public interface IHttpClientService<TClientOptions> : IBaseHttpClientService
|
public interface IHttpClientService<TClientOptions> : IBaseHttpClientService where TClientOptions : IHttpClientOptions
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<!-- NuGet Package Metadata -->
|
<!-- NuGet Package Metadata -->
|
||||||
@@ -9,18 +9,26 @@
|
|||||||
<Authors>Digital Data GmbH</Authors>
|
<Authors>Digital Data GmbH</Authors>
|
||||||
<Company>Digital Data GmbH</Company>
|
<Company>Digital Data GmbH</Company>
|
||||||
<Product>DigitalData.Core.Abstractions</Product>
|
<Product>DigitalData.Core.Abstractions</Product>
|
||||||
<Description>This package contains abstractions for the DigitalData.Core.Abstractions library, developed according to the principles of Clean Architecture. It promotes separation of concerns and enables independent core logic.</Description>
|
<Description>This package contains abstractions for the DigitalData.Core library, developed according to the principles of Clean Architecture. It promotes separation of concerns and enables independent core logic.</Description>
|
||||||
<PackageTags>digital data core abstractions clean architecture</PackageTags>
|
<PackageTags>digital data core abstractions clean architecture</PackageTags>
|
||||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||||
<Copyright>Copyright 2024</Copyright>
|
<Copyright>Copyright 2024</Copyright>
|
||||||
<PackageProjectUrl></PackageProjectUrl>
|
<PackageProjectUrl></PackageProjectUrl>
|
||||||
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
|
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
|
||||||
<PackAsTool>False</PackAsTool>
|
<PackAsTool>False</PackAsTool>
|
||||||
<NeutralLanguage>aa-DJ</NeutralLanguage>
|
<PackageIcon>core_icon.png</PackageIcon>
|
||||||
<PackageIcon>Assets\icon.png</PackageIcon>
|
<Version>3.1.0</Version>
|
||||||
<Version>2.0.0.0</Version>
|
<AssemblyVersion>3.1.0</AssemblyVersion>
|
||||||
|
<FileVersion>3.1.0</FileVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="..\..\nuget-package-icons\core_icon.png">
|
||||||
|
<Pack>True</Pack>
|
||||||
|
<PackagePath>\</PackagePath>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="7.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.4" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.4" />
|
||||||
@@ -33,12 +41,4 @@
|
|||||||
<ProjectReference Include="..\DigitalData.Core.DTO\DigitalData.Core.DTO.csproj" />
|
<ProjectReference Include="..\DigitalData.Core.DTO\DigitalData.Core.DTO.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<None Update="Assets\icon.png">
|
|
||||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
|
||||||
<Pack>True</Pack>
|
|
||||||
<PackagePath>\</PackagePath>
|
|
||||||
</None>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace DigitalData.Core.Abstractions.Security
|
||||||
|
{
|
||||||
|
public interface IAsymmetricDecryptor : IAsymmetricPrivateKey
|
||||||
|
{
|
||||||
|
byte[] Decrypt(byte[] data);
|
||||||
|
|
||||||
|
IAsymmetricEncryptor Encryptor { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace DigitalData.Core.Abstractions.Security
|
||||||
|
{
|
||||||
|
public interface IAsymmetricEncryptor : IAsymmetricPublicKey
|
||||||
|
{
|
||||||
|
byte[] Encrypt(byte[] data);
|
||||||
|
}
|
||||||
|
}
|
||||||
9
DigitalData.Core.Abstractions/Security/IAsymmetricKey.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace DigitalData.Core.Abstractions.Security
|
||||||
|
{
|
||||||
|
public interface IAsymmetricKey
|
||||||
|
{
|
||||||
|
string? Id { get; }
|
||||||
|
|
||||||
|
string Content { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace DigitalData.Core.Abstractions.Security
|
||||||
|
{
|
||||||
|
public interface IAsymmetricKeyFactory
|
||||||
|
{
|
||||||
|
string CreatePrivateKeyPem(int? keySizeInBits = null, bool encrypt = false);
|
||||||
|
|
||||||
|
string CreateEncryptedPrivateKeyPem(
|
||||||
|
PbeEncryptionAlgorithm? pbeEncryptionAlgorithm = null,
|
||||||
|
HashAlgorithmName? hashAlgorithmName = null,
|
||||||
|
int? iterationCount = null,
|
||||||
|
int? keySizeInBits = null,
|
||||||
|
string? password = null);
|
||||||
|
|
||||||
|
string CreateEncryptedPrivateKeyPem(
|
||||||
|
PbeParameters pbeParameters,
|
||||||
|
int? keySizeInBits = null,
|
||||||
|
string? password = null);
|
||||||
|
|
||||||
|
IAsymmetricDecryptor CreateDecryptor(string pem, string? issuer = null, string? audience = null, bool encrypt = false, RSAEncryptionPadding? padding = null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace DigitalData.Core.Abstractions.Security
|
||||||
|
{
|
||||||
|
public interface IAsymmetricPrivateKey : IAsymmetricKey
|
||||||
|
{
|
||||||
|
bool IsEncrypted { get; }
|
||||||
|
|
||||||
|
IAsymmetricPublicKey PublicKey { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace DigitalData.Core.Abstractions.Security
|
||||||
|
{
|
||||||
|
public interface IAsymmetricPublicKey : IAsymmetricKey
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
|
||||||
|
namespace DigitalData.Core.Abstractions.Security
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Contains some information which used to create a security token. Designed to abstract <see cref="SecurityTokenDescriptor"/>
|
||||||
|
/// </summary>
|
||||||
|
public interface IAsymmetricTokenDescriptor : IAsymmetricPrivateKey, IUniqueSecurityContext
|
||||||
|
{
|
||||||
|
IAsymmetricTokenValidator Validator { get; }
|
||||||
|
|
||||||
|
TimeSpan Lifetime { get; init; }
|
||||||
|
|
||||||
|
#region SecurityTokenDescriptor Map
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the compression algorithm that will be used to compress the JWT token payload.
|
||||||
|
/// </summary>
|
||||||
|
string CompressionAlgorithm { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the <see cref="EncryptingCredentials"/> used to create a encrypted security token.
|
||||||
|
/// </summary>
|
||||||
|
EncryptingCredentials EncryptingCredentials { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the value of the 'expiration' claim. This value should be in UTC.
|
||||||
|
/// </summary>
|
||||||
|
DateTime? Expires { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the time the security token was issued. This value should be in UTC.
|
||||||
|
/// </summary>
|
||||||
|
DateTime? IssuedAt { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the notbefore time for the security token. This value should be in UTC.
|
||||||
|
/// </summary>
|
||||||
|
DateTime? NotBefore { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the token type.
|
||||||
|
/// <remarks> If provided, this will be added as the value for the 'typ' header parameter. In the case of a JWE, this will be added to both the inner (JWS) and the outer token (JWE) header. By default, the value used is 'JWT'.
|
||||||
|
/// If <see cref="AdditionalHeaderClaims"/> also contains 'typ' header claim value, it will override the TokenType provided here.
|
||||||
|
/// This value is used only for JWT tokens and not for SAML/SAML2 tokens</remarks>
|
||||||
|
/// </summary>
|
||||||
|
string TokenType { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the <see cref="Dictionary{TKey, TValue}"/> which contains any custom header claims that need to be added to the JWT token header.
|
||||||
|
/// The 'alg', 'kid', 'x5t', 'enc', and 'zip' claims are added by default based on the <see cref="SigningCredentials"/>,
|
||||||
|
/// <see cref="EncryptingCredentials"/>, and/or <see cref="CompressionAlgorithm"/> provided and SHOULD NOT be included in this dictionary as this
|
||||||
|
/// will result in an exception being thrown.
|
||||||
|
/// <remarks> These claims are only added to the outer header (in case of a JWE).</remarks>
|
||||||
|
/// </summary>
|
||||||
|
IDictionary<string, object> AdditionalHeaderClaims { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the <see cref="Dictionary{TKey, TValue}"/> which contains any custom header claims that need to be added to the inner JWT token header.
|
||||||
|
/// The 'alg', 'kid', 'x5t', 'enc', and 'zip' claims are added by default based on the <see cref="SigningCredentials"/>,
|
||||||
|
/// <see cref="EncryptingCredentials"/>, and/or <see cref="CompressionAlgorithm"/> provided and SHOULD NOT be included in this dictionary as this
|
||||||
|
/// will result in an exception being thrown.
|
||||||
|
/// <remarks>
|
||||||
|
/// For JsonWebTokenHandler, these claims are merged with <see cref="AdditionalHeaderClaims"/> while adding to the inner JWT header.
|
||||||
|
/// </remarks>
|
||||||
|
/// </summary>
|
||||||
|
IDictionary<string, object> AdditionalInnerHeaderClaims { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the <see cref="SigningCredentials"/> used to create a security token.
|
||||||
|
/// </summary>
|
||||||
|
SigningCredentials SigningCredentials { get; }
|
||||||
|
#endregion SecurityTokenDescriptor
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
|
||||||
|
namespace DigitalData.Core.Abstractions.Security
|
||||||
|
{
|
||||||
|
public interface IAsymmetricTokenValidator : IAsymmetricPublicKey
|
||||||
|
{
|
||||||
|
SecurityKey SecurityKey { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
11
DigitalData.Core.Abstractions/Security/ICryptoFactory.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
namespace DigitalData.Core.Abstractions.Security
|
||||||
|
{
|
||||||
|
public interface ICryptoFactory : IAsymmetricKeyFactory
|
||||||
|
{
|
||||||
|
IEnumerable<IAsymmetricDecryptor> Decryptors { get; }
|
||||||
|
|
||||||
|
IAsymmetricDecryptor VaultDecryptor { get; }
|
||||||
|
|
||||||
|
IEnumerable<IAsymmetricTokenDescriptor> TokenDescriptors { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
|
||||||
|
namespace DigitalData.Core.Abstractions.Security
|
||||||
|
{
|
||||||
|
public interface IJwtSignatureHandler<TPrincipal>
|
||||||
|
{
|
||||||
|
SecurityToken CreateToken(SecurityTokenDescriptor tokenDescriptor);
|
||||||
|
|
||||||
|
SecurityToken CreateToken(TPrincipal subject, IAsymmetricTokenDescriptor descriptor);
|
||||||
|
|
||||||
|
SecurityToken CreateToken(TPrincipal subject, string issuer, string audience);
|
||||||
|
|
||||||
|
string WriteToken(SecurityToken token);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
namespace DigitalData.Core.Abstractions.Security
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a unique security context that identifies an issuer and an audience.
|
||||||
|
/// </summary>
|
||||||
|
public interface IUniqueSecurityContext
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the issuer identifier for this security context.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The issuer typically represents the entity that issues a token or a cryptographic key.
|
||||||
|
/// </remarks>
|
||||||
|
string Issuer { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the audience identifier for this security context.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The audience typically represents the intended recipient or target of a token or cryptographic operation.
|
||||||
|
/// </remarks>
|
||||||
|
string Audience { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
62
DigitalData.Core.Abstractions/Security/SecurityExtensions.cs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace DigitalData.Core.Abstractions.Security
|
||||||
|
{
|
||||||
|
public static class SecurityExtensions
|
||||||
|
{
|
||||||
|
#region Unique Security Context
|
||||||
|
public static IEnumerable<TUniqueSecurityContext> GetByIssuer<TUniqueSecurityContext>(this IEnumerable<TUniqueSecurityContext> contextes, string issuer) where TUniqueSecurityContext: IUniqueSecurityContext
|
||||||
|
=> contextes.Where(c => c.Issuer == issuer);
|
||||||
|
|
||||||
|
public static IEnumerable<TUniqueSecurityContext> GetByAudience<TUniqueSecurityContext>(this IEnumerable<TUniqueSecurityContext> contextes, string audience) where TUniqueSecurityContext : IUniqueSecurityContext
|
||||||
|
=> contextes.Where(c => c.Audience == audience);
|
||||||
|
|
||||||
|
public static TUniqueSecurityContext Get<TUniqueSecurityContext>(this IEnumerable<TUniqueSecurityContext> contextes, string issuer, string audience) where TUniqueSecurityContext : IUniqueSecurityContext
|
||||||
|
=> contextes.Where(c => c.Issuer == issuer && c.Audience == audience).SingleOrDefault()
|
||||||
|
?? throw new InvalidOperationException($"Exactly one {typeof(TUniqueSecurityContext).Name} must exist with Issuer: '{issuer}' and Audience: '{audience}'.");
|
||||||
|
|
||||||
|
public static bool TryGet<TUniqueSecurityContext>(this IEnumerable<TUniqueSecurityContext> contextes, string issuer, string audience, out TUniqueSecurityContext context) where TUniqueSecurityContext : IUniqueSecurityContext
|
||||||
|
{
|
||||||
|
#pragma warning disable CS8601 // Possible null reference assignment.
|
||||||
|
context = contextes.SingleOrDefault(c => c.Issuer == issuer && c.Audience == audience);
|
||||||
|
#pragma warning restore CS8601 // Possible null reference assignment.
|
||||||
|
return context is not null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TUniqueSecurityContext Match<TUniqueSecurityContext>(this IEnumerable<TUniqueSecurityContext> contextes, IUniqueSecurityContext lookupContext) where TUniqueSecurityContext : IUniqueSecurityContext
|
||||||
|
=> contextes.Get(lookupContext.Issuer, lookupContext.Audience);
|
||||||
|
|
||||||
|
public static bool TryMatch<TUniqueSecurityContext>(this IEnumerable<TUniqueSecurityContext> contextes, IUniqueSecurityContext lookupContext, out TUniqueSecurityContext context) where TUniqueSecurityContext : IUniqueSecurityContext
|
||||||
|
=> contextes.TryGet(lookupContext.Issuer, lookupContext.Audience, out context);
|
||||||
|
#endregion Unique Security Context
|
||||||
|
|
||||||
|
#region De/serilization
|
||||||
|
internal static byte[] Base64ToByte(this string base64String) => Convert.FromBase64String(base64String);
|
||||||
|
|
||||||
|
internal static string BytesToString(this byte[] bytes) => Encoding.UTF8.GetString(bytes);
|
||||||
|
|
||||||
|
internal static string ToBase64String(this byte[] bytes) => Convert.ToBase64String(bytes);
|
||||||
|
|
||||||
|
internal static byte[] ToBytes(this string str) => System.Text.Encoding.UTF8.GetBytes(str);
|
||||||
|
|
||||||
|
public static string Decrypt(this IAsymmetricDecryptor decryptor, string data) => decryptor
|
||||||
|
.Decrypt(data.Base64ToByte()).BytesToString();
|
||||||
|
#endregion De/serilization
|
||||||
|
|
||||||
|
#region Asymmetric Encryptor
|
||||||
|
public static string Encrypt(this IAsymmetricEncryptor encryptor, string data) => encryptor.Encrypt(data.ToBytes()).ToBase64String();
|
||||||
|
#endregion Asymmetric Encryptor
|
||||||
|
|
||||||
|
#region Jwt Signature Handler
|
||||||
|
public static string WriteToken<TPrincipal>(this IJwtSignatureHandler<TPrincipal> handler, SecurityTokenDescriptor descriptor)
|
||||||
|
=> handler.WriteToken(handler.CreateToken(descriptor));
|
||||||
|
|
||||||
|
public static string WriteToken<TPrincipal>(this IJwtSignatureHandler<TPrincipal> handler, TPrincipal subject, IAsymmetricTokenDescriptor descriptor)
|
||||||
|
=> handler.WriteToken(handler.CreateToken(subject: subject, descriptor: descriptor));
|
||||||
|
|
||||||
|
public static string WriteToken<TPrincipal>(this IJwtSignatureHandler<TPrincipal> handler, TPrincipal subject, string issuer, string audience)
|
||||||
|
=> handler.WriteToken(handler.CreateToken(subject: subject, issuer: issuer, audience: audience));
|
||||||
|
#endregion Jwt Signature Handler
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 1020 KiB |
@@ -19,7 +19,7 @@ namespace DigitalData.Core.Application
|
|||||||
/// and a culture-specific translation service for any necessary text translations, ensuring a versatile and internationalized approach to CRUD operations.
|
/// and a culture-specific translation service for any necessary text translations, ensuring a versatile and internationalized approach to CRUD operations.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public class BasicCRUDService<TCRUDRepository, TDto, TEntity, TId> :
|
public class BasicCRUDService<TCRUDRepository, TDto, TEntity, TId> :
|
||||||
CRUDService<TCRUDRepository, TDto, TDto, TDto, TEntity, TId>, IBasicCRUDService<TDto, TEntity, TId>
|
CRUDService<TCRUDRepository, TDto, TDto, TEntity, TId>, IBasicCRUDService<TDto, TEntity, TId>
|
||||||
where TCRUDRepository : ICRUDRepository<TEntity, TId> where TDto : class, IUnique<TId> where TEntity : class, IUnique<TId>
|
where TCRUDRepository : ICRUDRepository<TEntity, TId> where TDto : class, IUnique<TId> where TEntity : class, IUnique<TId>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -12,11 +12,10 @@ namespace DigitalData.Core.Application
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TCreateDto">The DTO type for create operations.</typeparam>
|
/// <typeparam name="TCreateDto">The DTO type for create operations.</typeparam>
|
||||||
/// <typeparam name="TReadDto">The DTO type for read operations.</typeparam>
|
/// <typeparam name="TReadDto">The DTO type for read operations.</typeparam>
|
||||||
/// <typeparam name="TUpdateDto">The DTO type for update operations.</typeparam>
|
|
||||||
/// <typeparam name="TEntity">The entity type.</typeparam>
|
/// <typeparam name="TEntity">The entity type.</typeparam>
|
||||||
/// <typeparam name="TId">The type of the identifier for the entity.</typeparam>
|
/// <typeparam name="TId">The type of the identifier for the entity.</typeparam>
|
||||||
public class CRUDService<TCRUDRepository, TCreateDto, TReadDto, TUpdateDto, TEntity, TId> : ReadService<TCRUDRepository, TReadDto, TEntity, TId>, ICRUDService<TCreateDto, TReadDto, TUpdateDto, TEntity, TId>
|
public class CRUDService<TCRUDRepository, TCreateDto, TReadDto, TEntity, TId> : ReadService<TCRUDRepository, TReadDto, TEntity, TId>, ICRUDService<TCreateDto, TReadDto, TEntity, TId>
|
||||||
where TCRUDRepository : ICRUDRepository<TEntity, TId> where TCreateDto : class where TReadDto : class where TUpdateDto : IUnique<TId> where TEntity : class, IUnique<TId>
|
where TCRUDRepository : ICRUDRepository<TEntity, TId> where TCreateDto : class where TReadDto : class where TEntity : class, IUnique<TId>
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -45,7 +44,7 @@ namespace DigitalData.Core.Application
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="updateDto">The DTO to update an entity from.</param>
|
/// <param name="updateDto">The DTO to update an entity from.</param>
|
||||||
/// <returns>A service message indicating success or failure.</returns>
|
/// <returns>A service message indicating success or failure.</returns>
|
||||||
public virtual async Task<Result> UpdateAsync(TUpdateDto updateDto)
|
public virtual async Task<Result> UpdateAsync<TUpdateDto>(TUpdateDto updateDto) where TUpdateDto : IUnique<TId>
|
||||||
{
|
{
|
||||||
var currentEntitiy = await _repository.ReadByIdAsync(updateDto.Id);
|
var currentEntitiy = await _repository.ReadByIdAsync(updateDto.Id);
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ namespace DigitalData.Core.Application
|
|||||||
/// <typeparam name="TCRUDRepository">The repository type that provides CRUD operations for entities of type TEntity.</typeparam>
|
/// <typeparam name="TCRUDRepository">The repository type that provides CRUD operations for entities of type TEntity.</typeparam>
|
||||||
/// <typeparam name="TCreateDto">The DTO type used for create operations.</typeparam>
|
/// <typeparam name="TCreateDto">The DTO type used for create operations.</typeparam>
|
||||||
/// <typeparam name="TReadDto">The DTO type used for read operations.</typeparam>
|
/// <typeparam name="TReadDto">The DTO type used for read operations.</typeparam>
|
||||||
/// <typeparam name="TUpdateDto">The DTO type used for update operations.</typeparam>
|
|
||||||
/// <typeparam name="TEntity">The entity type corresponding to the DTOs.</typeparam>
|
/// <typeparam name="TEntity">The entity type corresponding to the DTOs.</typeparam>
|
||||||
/// <typeparam name="TId">The type of the entity's identifier.</typeparam>
|
/// <typeparam name="TId">The type of the entity's identifier.</typeparam>
|
||||||
/// <typeparam name="TProfile">The AutoMapper profile type for configuring mappings between the DTOs and the entity.</typeparam>
|
/// <typeparam name="TProfile">The AutoMapper profile type for configuring mappings between the DTOs and the entity.</typeparam>
|
||||||
@@ -48,9 +47,9 @@ namespace DigitalData.Core.Application
|
|||||||
/// <param name="configureService">An optional action to configure additional services for the CRUD service.</param>
|
/// <param name="configureService">An optional action to configure additional services for the CRUD service.</param>
|
||||||
/// <returns>The original <see cref="IServiceCollection"/> instance, allowing further configuration.</returns>
|
/// <returns>The original <see cref="IServiceCollection"/> instance, allowing further configuration.</returns>
|
||||||
public static IServiceCollection AddCleanCRUDService<TCRUDRepository, TCreateDto, TReadDto, TUpdateDto, TEntity, TId, TProfile>(this IServiceCollection services, Action<IServiceCollection>? configureService = null)
|
public static IServiceCollection AddCleanCRUDService<TCRUDRepository, TCreateDto, TReadDto, TUpdateDto, TEntity, TId, TProfile>(this IServiceCollection services, Action<IServiceCollection>? configureService = null)
|
||||||
where TCRUDRepository : ICRUDRepository<TEntity, TId> where TCreateDto : class where TReadDto : class where TUpdateDto : class, IUnique<TId> where TEntity : class, IUnique<TId> where TProfile : Profile
|
where TCRUDRepository : ICRUDRepository<TEntity, TId> where TCreateDto : class where TReadDto : class, IUnique<TId> where TEntity : class, IUnique<TId> where TProfile : Profile
|
||||||
{
|
{
|
||||||
services.AddScoped<ICRUDService<TCreateDto, TReadDto, TUpdateDto, TEntity, TId>, CRUDService<TCRUDRepository, TCreateDto, TReadDto, TUpdateDto, TEntity, TId>>();
|
services.AddScoped<ICRUDService<TCreateDto, TReadDto, TEntity, TId>, CRUDService<TCRUDRepository, TCreateDto, TReadDto, TEntity, TId>>();
|
||||||
configureService?.Invoke(services);
|
configureService?.Invoke(services);
|
||||||
|
|
||||||
services.AddAutoMapper(typeof(TProfile).Assembly);
|
services.AddAutoMapper(typeof(TProfile).Assembly);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||||
@@ -11,14 +11,16 @@
|
|||||||
<Company>Digital Data GmbH</Company>
|
<Company>Digital Data GmbH</Company>
|
||||||
<Product>DigitalData.Core.Application</Product>
|
<Product>DigitalData.Core.Application</Product>
|
||||||
<Copyright>Copyright 2024</Copyright>
|
<Copyright>Copyright 2024</Copyright>
|
||||||
<PackageIcon>icon.png</PackageIcon>
|
<PackageIcon>core_icon.png</PackageIcon>
|
||||||
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
|
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
|
||||||
<PackageTags>digital data core application clean architecture</PackageTags>
|
<PackageTags>digital data core application clean architecture</PackageTags>
|
||||||
<Version>2.0.0.0</Version>
|
<Version>3.0.1</Version>
|
||||||
|
<AssemblyVersion>3.0.1</AssemblyVersion>
|
||||||
|
<FileVersion>3.0.1</FileVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\DigitalData.Core.Abstractions\Assets\icon.png">
|
<None Include="..\..\nuget-package-icons\core_icon.png">
|
||||||
<Pack>True</Pack>
|
<Pack>True</Pack>
|
||||||
<PackagePath>\</PackagePath>
|
<PackagePath>\</PackagePath>
|
||||||
</None>
|
</None>
|
||||||
@@ -39,11 +41,4 @@
|
|||||||
<ProjectReference Include="..\DigitalData.Core.Abstractions\DigitalData.Core.Abstractions.csproj" />
|
<ProjectReference Include="..\DigitalData.Core.Abstractions\DigitalData.Core.Abstractions.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<None Update="Assets\icon.png">
|
|
||||||
<PackagePath>\</PackagePath>
|
|
||||||
<Pack>True</Pack>
|
|
||||||
</None>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
<ImportGroup Condition=" '$(TargetFramework)' == 'net7.0' AND '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||||
|
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\7.0.0\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\7.0.0\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets')" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition=" '$(TargetFramework)' == 'net8.0' AND '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||||
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\7.0.0\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\7.0.0\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets')" />
|
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\7.0.0\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\7.0.0\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets')" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
Before Width: | Height: | Size: 1020 KiB |
@@ -1,44 +1,113 @@
|
|||||||
using DigitalData.Core.Abstractions.Client;
|
using DigitalData.Core.Abstractions.Client;
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Web;
|
||||||
|
|
||||||
namespace DigitalData.Core.Client
|
namespace DigitalData.Core.Client
|
||||||
{
|
{
|
||||||
public class BaseHttpClientService : IBaseHttpClientService
|
public class BaseHttpClientService : IBaseHttpClientService
|
||||||
{
|
{
|
||||||
protected readonly HttpClient _client;
|
protected readonly HttpClient _client;
|
||||||
protected readonly CookieContainer _cookies;
|
protected readonly CookieContainer _cookies;
|
||||||
|
|
||||||
[StringSyntax("Uri")]
|
[StringSyntax("Uri")]
|
||||||
public string Uri { get; init; }
|
protected readonly string _uri;
|
||||||
|
|
||||||
public BaseHttpClientService(HttpClient client, CookieContainer cookieContainer, IOptions<HttpClientOptions> clientOptions)
|
protected readonly string _path;
|
||||||
|
|
||||||
|
protected IEnumerable<KeyValuePair<string, object>>? _headers;
|
||||||
|
|
||||||
|
protected IEnumerable<KeyValuePair<string, object?>>? _queryParams;
|
||||||
|
|
||||||
|
internal BaseHttpClientService(HttpClient client, CookieContainer cookieContainer, IHttpClientOptions clientOptions)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_cookies = cookieContainer;
|
_cookies = cookieContainer;
|
||||||
Uri = clientOptions.Value.Uri;
|
_uri = clientOptions.Uri.Trim(URI_TRIM_CHARS);
|
||||||
|
_path = clientOptions.Path?.Trim(URI_TRIM_CHARS) ?? string.Empty;
|
||||||
|
_headers = clientOptions.Headers;
|
||||||
|
_queryParams = clientOptions.QueryParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CookieCollection GetCookies(string route = "") => _cookies.GetCookies(uri: new Uri(Uri + route));
|
public CookieCollection GetCookies(string path = "") => _cookies.GetCookies(uri: new Uri(UriCombine(_uri, path, path.Trim(URI_TRIM_CHARS))));
|
||||||
|
|
||||||
public async Task<HttpResponseMessage> FetchAsync(
|
public async Task<HttpResponseMessage> FetchAsync(
|
||||||
string route = "",
|
string? scheme = null,
|
||||||
|
int? port = null,
|
||||||
|
string path = "",
|
||||||
|
IEnumerable<KeyValuePair<string, object?>>? queryParams = null,
|
||||||
HttpMethod? method = null,
|
HttpMethod? method = null,
|
||||||
HttpContent? body = null,
|
HttpContent? body = null,
|
||||||
Dictionary<string, string>? form = null,
|
IEnumerable<KeyValuePair<string, object>>? form = null,
|
||||||
|
IEnumerable<KeyValuePair<string, object>>? headers = null,
|
||||||
bool sendWithCookie = true,
|
bool sendWithCookie = true,
|
||||||
bool saveCookie = true
|
bool saveCookie = true
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
// merge with default headers
|
||||||
|
if(_headers is not null)
|
||||||
|
{
|
||||||
|
if (headers is null)
|
||||||
|
headers = _headers;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var mergedHeaders = headers.ToList();
|
||||||
|
mergedHeaders.AddRange(_headers);
|
||||||
|
headers = mergedHeaders;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add default query parameters
|
||||||
|
if(_queryParams is not null)
|
||||||
|
{
|
||||||
|
if (queryParams is null)
|
||||||
|
queryParams = _queryParams;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var mergedQueryParams = queryParams.ToList();
|
||||||
|
mergedQueryParams.AddRange(_queryParams);
|
||||||
|
queryParams = mergedQueryParams;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// set default HTTP method as GET
|
// set default HTTP method as GET
|
||||||
method ??= HttpMethod.Get;
|
method ??= HttpMethod.Get;
|
||||||
|
|
||||||
// create URL
|
// create URL
|
||||||
var requestUriStr = Uri + route;
|
var uriBuilder = new UriBuilder(_uri);
|
||||||
var requestUri = new Uri(requestUriStr);
|
if (scheme is not null)
|
||||||
|
uriBuilder.Scheme = scheme;
|
||||||
|
if (port is int portInt)
|
||||||
|
uriBuilder.Port = portInt;
|
||||||
|
uriBuilder.Path = UriCombine(_path, path?.Trim(URI_TRIM_CHARS) ?? string.Empty);
|
||||||
|
|
||||||
var requestMessage = new HttpRequestMessage(method, requestUriStr);
|
// Add query parameters if provided
|
||||||
|
if (queryParams?.Any() ?? false)
|
||||||
|
{
|
||||||
|
var query = HttpUtility.ParseQueryString(uriBuilder.Query);
|
||||||
|
|
||||||
|
var flagParams = queryParams.Where(param => param.Value is null).Select(param => param.Key);
|
||||||
|
|
||||||
|
var valueParams = queryParams.Where(param => param.Value is not null);
|
||||||
|
|
||||||
|
foreach (var param in valueParams)
|
||||||
|
query[param.Key] = param.Value switch
|
||||||
|
{
|
||||||
|
bool b => b.ToString().ToLower(),
|
||||||
|
_ => param.Value.ToString()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (flagParams.Any())
|
||||||
|
uriBuilder.Query = string.Join(QUERY_SEPARATOR, query.ToString(), string.Join(QUERY_SEPARATOR, flagParams));
|
||||||
|
else uriBuilder.Query = query.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
var requestUri = uriBuilder.Uri;
|
||||||
|
|
||||||
|
var requestMessage = new HttpRequestMessage(method, requestUri);
|
||||||
|
|
||||||
|
// Add headers if provided
|
||||||
|
headers?.ForEach(header => requestMessage.Headers.Add(header.Key, header.Value.ToString()));
|
||||||
|
|
||||||
// Add cookie to request
|
// Add cookie to request
|
||||||
if (sendWithCookie)
|
if (sendWithCookie)
|
||||||
@@ -56,7 +125,7 @@ namespace DigitalData.Core.Client
|
|||||||
else if (body != null)
|
else if (body != null)
|
||||||
requestMessage.Content = body;
|
requestMessage.Content = body;
|
||||||
else if (form != null)
|
else if (form != null)
|
||||||
requestMessage.Content = new FormUrlEncodedContent(form);
|
requestMessage.Content = new FormUrlEncodedContent(form.Select(e => KeyValuePair.Create(e.Key, e.Value.ToString())));
|
||||||
|
|
||||||
var response = await _client.SendAsync(requestMessage);
|
var response = await _client.SendAsync(requestMessage);
|
||||||
|
|
||||||
@@ -68,5 +137,11 @@ namespace DigitalData.Core.Client
|
|||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static readonly char[] URI_TRIM_CHARS = { '\\', '/', ' ' };
|
||||||
|
|
||||||
|
internal static string UriCombine(params string[] paths) => System.IO.Path.Combine(paths).Replace("\\", "/");
|
||||||
|
|
||||||
|
internal static readonly char QUERY_SEPARATOR = '&';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,33 +1,35 @@
|
|||||||
using DigitalData.Core.Abstractions.Client;
|
using DigitalData.Core.Abstractions.Client;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
|
||||||
namespace DigitalData.Core.Client
|
namespace DigitalData.Core.Client
|
||||||
{
|
{
|
||||||
public static class DIExtensions
|
public static class DIExtensions
|
||||||
{
|
{
|
||||||
public static IServiceCollection AddHttpClientService(this IServiceCollection services, string uri)
|
internal static IServiceCollection AddHttpClientServiceDefaults(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.TryAddSingleton<HttpClient>();
|
services.TryAddSingleton<HttpClient>();
|
||||||
services.TryAddSingleton<CookieContainer>();
|
services.TryAddSingleton<CookieContainer>();
|
||||||
services.AddSingleton<IBaseHttpClientService, BaseHttpClientService>();
|
|
||||||
services.Configure<HttpClientOptions>(opt => opt.Uri = uri);
|
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IServiceCollection AddHttpClientService<TClientOptions>(this IServiceCollection services, Action<TClientOptions>? clientOptions = null, bool setAsDefaultBase = false)
|
public static IServiceCollection AddHttpClientService<THttpClientOptions>(this IServiceCollection services, IConfigurationSection section)
|
||||||
where TClientOptions : HttpClientOptions
|
where THttpClientOptions : class, IHttpClientOptions
|
||||||
{
|
{
|
||||||
services.TryAddSingleton<HttpClient>();
|
services.AddHttpClientServiceDefaults();
|
||||||
services.TryAddSingleton<CookieContainer>();
|
services.TryAddSingleton<IHttpClientService<THttpClientOptions>, HttpClientService<THttpClientOptions>>();
|
||||||
services.AddSingleton<IHttpClientService<TClientOptions>, HttpClientService<TClientOptions>>();
|
return services.Configure<THttpClientOptions>(section);
|
||||||
services.Configure(clientOptions ?? (_ => { }));
|
}
|
||||||
|
|
||||||
if (setAsDefaultBase)
|
|
||||||
services.AddSingleton<IBaseHttpClientService, HttpClientService<TClientOptions>>();
|
|
||||||
|
|
||||||
|
public static IServiceCollection AddHttpClientService<THttpClientOptions>(this IServiceCollection services, THttpClientOptions options)
|
||||||
|
where THttpClientOptions : class, IHttpClientOptions
|
||||||
|
{
|
||||||
|
services.AddHttpClientServiceDefaults();
|
||||||
|
services.TryAddSingleton<IHttpClientService<THttpClientOptions>, HttpClientService<THttpClientOptions>>();
|
||||||
|
services.TryAddSingleton(Options.Create(options));
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,35 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<Description>This package provides HTTP client extension methods for the DigitalData.Core library, offering simplified and asynchronous methods for fetching and handling HTTP responses. It includes utility methods for sending GET requests, reading response content as text or JSON, and deserializing JSON into dynamic or strongly-typed objects using Newtonsoft.Json. These extensions facilitate efficient and easy-to-read HTTP interactions in client applications.</Description>
|
<Description>This package provides HTTP client extension methods for the DigitalData.Core library, offering simplified and asynchronous methods for fetching and handling HTTP responses. It includes utility methods for sending GET requests, reading response content as text or JSON, and deserializing JSON into dynamic or strongly-typed objects using Newtonsoft.Json. These extensions facilitate efficient and easy-to-read HTTP interactions in client applications.</Description>
|
||||||
<PackageId>DigitalData.Core.Client</PackageId>
|
<PackageId>DigitalData.Core.Client</PackageId>
|
||||||
<Version>1.0.1.1</Version>
|
<Version>2.0.3</Version>
|
||||||
<Authors>Digital Data GmbH</Authors>
|
<Authors>Digital Data GmbH</Authors>
|
||||||
<Company>Digital Data GmbH</Company>
|
<Company>Digital Data GmbH</Company>
|
||||||
<Product>Digital Data GmbH</Product>
|
<Product>Digital Data GmbH</Product>
|
||||||
<Copyright>Copyright 2024</Copyright>
|
<Copyright>Copyright 2024</Copyright>
|
||||||
<PackageProjectUrl></PackageProjectUrl>
|
<PackageProjectUrl></PackageProjectUrl>
|
||||||
<PackageIcon>Assets\icon.png</PackageIcon>
|
<PackageIcon>core_icon.png</PackageIcon>
|
||||||
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
|
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
|
||||||
<PackageTags>digital data core http client json serilization</PackageTags>
|
<PackageTags>digital data core http client json serilization</PackageTags>
|
||||||
|
<AssemblyVersion>2.0.3</AssemblyVersion>
|
||||||
|
<FileVersion>2.0.3</FileVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="..\..\nuget-package-icons\core_icon.png">
|
||||||
|
<Pack>True</Pack>
|
||||||
|
<PackagePath>\</PackagePath>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Options" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Options" Version="7.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="7.0.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace DigitalData.Core.Client
|
|
||||||
{
|
|
||||||
public class HttpClientOptions
|
|
||||||
{
|
|
||||||
public string Uri { get; set; } = string.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,9 +5,9 @@ using System.Net;
|
|||||||
namespace DigitalData.Core.Client
|
namespace DigitalData.Core.Client
|
||||||
{
|
{
|
||||||
public class HttpClientService<TClientOptions> : BaseHttpClientService, IHttpClientService<TClientOptions>, IBaseHttpClientService
|
public class HttpClientService<TClientOptions> : BaseHttpClientService, IHttpClientService<TClientOptions>, IBaseHttpClientService
|
||||||
where TClientOptions : HttpClientOptions
|
where TClientOptions : class, IHttpClientOptions
|
||||||
{
|
{
|
||||||
public HttpClientService(HttpClient client, CookieContainer cookieContainer, IOptions<TClientOptions> clientOptions) : base(client, cookieContainer, clientOptions)
|
public HttpClientService(HttpClient client, CookieContainer cookieContainer, IOptions<TClientOptions> clientOptions) : base(client, cookieContainer, clientOptions.Value)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace DigitalData.Core.Client
|
|||||||
|
|
||||||
public static T Provide<T>() where T : notnull => _lazyProvider.Value.GetRequiredService<T>();
|
public static T Provide<T>() where T : notnull => _lazyProvider.Value.GetRequiredService<T>();
|
||||||
|
|
||||||
public static IHttpClientService<TOptions> ProvideHttpClientService<TOptions>() where TOptions : notnull
|
public static IHttpClientService<TOptions> ProvideHttpClientService<TOptions>() where TOptions : IHttpClientOptions
|
||||||
=> _lazyProvider.Value.GetRequiredService<IHttpClientService<TOptions>>();
|
=> _lazyProvider.Value.GetRequiredService<IHttpClientService<TOptions>>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
|
||||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
|
||||||
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
|
|
||||||
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
|
|
||||||
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
|
|
||||||
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
|
|
||||||
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\tekh\.nuget\packages\;D:\ProgramFiles\DevExpress 21.2\Components\Offline Packages</NuGetPackageFolders>
|
|
||||||
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
|
|
||||||
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.9.1</NuGetToolVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
|
||||||
<SourceRoot Include="C:\Users\tekh\.nuget\packages\" />
|
|
||||||
<SourceRoot Include="D:\ProgramFiles\DevExpress 21.2\Components\Offline Packages\" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
|
||||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
|
||||||
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\7.0.0\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\7.0.0\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets')" />
|
|
||||||
</ImportGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
using DigitalData.Common.CultureServices;
|
|
||||||
using DigitalData.Core.Contracts.CultureServices;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
|
|
||||||
namespace DigitalData.Core.CultureServices
|
|
||||||
{
|
|
||||||
public static class DIExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Registers the KeyTranslationService and its dependencies in the dependency injection container.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="services">The IServiceCollection instance to register the services with.</param>
|
|
||||||
public static IServiceCollection AddKeyTranslationService(this IServiceCollection services)
|
|
||||||
{
|
|
||||||
services.AddTransient<IKeyTranslationService, KeyTranslationService>();
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="7.0.16" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\DigitalData.Core.Contracts\DigitalData.Core.Contracts.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
using DigitalData.Core.Contracts.CultureServices;
|
|
||||||
using Microsoft.Extensions.Localization;
|
|
||||||
|
|
||||||
namespace DigitalData.Common.CultureServices
|
|
||||||
{
|
|
||||||
public class KeyTranslationService<TResouce> : IKeyTranslationService
|
|
||||||
{
|
|
||||||
private readonly IStringLocalizer<TResouce> _localizer;
|
|
||||||
|
|
||||||
public KeyTranslationService(IStringLocalizer<TResouce> localizer)
|
|
||||||
{
|
|
||||||
_localizer = localizer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Translate(string key, params object[] arguments) => _localizer[key, arguments];
|
|
||||||
|
|
||||||
|
|
||||||
public string Translate(Enum key, params object[] arguments) => Translate(key.ToString(), arguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"profiles": {
|
|
||||||
"DigitalData.Core.CultureServices": {
|
|
||||||
"commandName": "Project",
|
|
||||||
"launchBrowser": true,
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
},
|
|
||||||
"applicationUrl": "https://localhost:61600;http://localhost:61602"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
using DigitalData.Core.Contracts.CultureServices;
|
|
||||||
|
|
||||||
namespace DigitalData.Core.CultureServices
|
|
||||||
{
|
|
||||||
public static class TranslationExtensions
|
|
||||||
{
|
|
||||||
public static string TranslateWith(this string key, IKeyTranslationService keyTranslationService) => keyTranslationService.Translate(key: key);
|
|
||||||
|
|
||||||
public static string TranslateWith(this Enum key, IKeyTranslationService keyTranslationService) => keyTranslationService.Translate(key: key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,576 +0,0 @@
|
|||||||
{
|
|
||||||
"runtimeTarget": {
|
|
||||||
"name": ".NETCoreApp,Version=v7.0",
|
|
||||||
"signature": ""
|
|
||||||
},
|
|
||||||
"compilationOptions": {},
|
|
||||||
"targets": {
|
|
||||||
".NETCoreApp,Version=v7.0": {
|
|
||||||
"DigitalData.Core.CultureServices/1.0.0": {
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.Extensions.Localization": "7.0.16",
|
|
||||||
"WebCore.Contracts": "1.0.1",
|
|
||||||
"DigitalData.Core.Contracts": "1.0.1.0"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"DigitalData.Core.CultureServices.dll": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Caching.Abstractions/7.0.0": {
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.Extensions.Primitives": "7.0.0"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/net7.0/Microsoft.Extensions.Caching.Abstractions.dll": {
|
|
||||||
"assemblyVersion": "7.0.0.0",
|
|
||||||
"fileVersion": "7.0.22.51805"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Caching.Memory/7.0.0": {
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.Extensions.Caching.Abstractions": "7.0.0",
|
|
||||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0",
|
|
||||||
"Microsoft.Extensions.Logging.Abstractions": "7.0.1",
|
|
||||||
"Microsoft.Extensions.Options": "7.0.1",
|
|
||||||
"Microsoft.Extensions.Primitives": "7.0.0"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/net7.0/Microsoft.Extensions.Caching.Memory.dll": {
|
|
||||||
"assemblyVersion": "7.0.0.0",
|
|
||||||
"fileVersion": "7.0.22.51805"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Configuration.Abstractions/7.0.0": {
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.Extensions.Primitives": "7.0.0"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/net7.0/Microsoft.Extensions.Configuration.Abstractions.dll": {
|
|
||||||
"assemblyVersion": "7.0.0.0",
|
|
||||||
"fileVersion": "7.0.22.51805"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Configuration.Binder/7.0.4": {
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.Extensions.Configuration.Abstractions": "7.0.0"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/net7.0/Microsoft.Extensions.Configuration.Binder.dll": {
|
|
||||||
"assemblyVersion": "7.0.0.0",
|
|
||||||
"fileVersion": "7.0.423.11508"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.DependencyInjection.Abstractions/7.0.0": {
|
|
||||||
"runtime": {
|
|
||||||
"lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
|
|
||||||
"assemblyVersion": "7.0.0.0",
|
|
||||||
"fileVersion": "7.0.22.51805"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Localization/7.0.16": {
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0",
|
|
||||||
"Microsoft.Extensions.Localization.Abstractions": "7.0.16",
|
|
||||||
"Microsoft.Extensions.Logging.Abstractions": "7.0.1",
|
|
||||||
"Microsoft.Extensions.Options": "7.0.1"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/net7.0/Microsoft.Extensions.Localization.dll": {
|
|
||||||
"assemblyVersion": "7.0.0.0",
|
|
||||||
"fileVersion": "7.0.1624.6815"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Localization.Abstractions/7.0.16": {
|
|
||||||
"runtime": {
|
|
||||||
"lib/net7.0/Microsoft.Extensions.Localization.Abstractions.dll": {
|
|
||||||
"assemblyVersion": "7.0.0.0",
|
|
||||||
"fileVersion": "7.0.1624.6815"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Logging.Abstractions/7.0.1": {
|
|
||||||
"runtime": {
|
|
||||||
"lib/net7.0/Microsoft.Extensions.Logging.Abstractions.dll": {
|
|
||||||
"assemblyVersion": "7.0.0.0",
|
|
||||||
"fileVersion": "7.0.723.27404"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Options/7.0.1": {
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0",
|
|
||||||
"Microsoft.Extensions.Primitives": "7.0.0"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/net7.0/Microsoft.Extensions.Options.dll": {
|
|
||||||
"assemblyVersion": "7.0.0.0",
|
|
||||||
"fileVersion": "7.0.323.6910"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Primitives/7.0.0": {
|
|
||||||
"runtime": {
|
|
||||||
"lib/net7.0/Microsoft.Extensions.Primitives.dll": {
|
|
||||||
"assemblyVersion": "7.0.0.0",
|
|
||||||
"fileVersion": "7.0.22.51805"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Microsoft.IdentityModel.Abstractions/7.5.1": {
|
|
||||||
"runtime": {
|
|
||||||
"lib/net6.0/Microsoft.IdentityModel.Abstractions.dll": {
|
|
||||||
"assemblyVersion": "7.5.1.0",
|
|
||||||
"fileVersion": "7.5.1.50405"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Microsoft.IdentityModel.JsonWebTokens/7.5.1": {
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.IdentityModel.Tokens": "7.5.1"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/net6.0/Microsoft.IdentityModel.JsonWebTokens.dll": {
|
|
||||||
"assemblyVersion": "7.5.1.0",
|
|
||||||
"fileVersion": "7.5.1.50405"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Microsoft.IdentityModel.Logging/7.5.1": {
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.IdentityModel.Abstractions": "7.5.1"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/net6.0/Microsoft.IdentityModel.Logging.dll": {
|
|
||||||
"assemblyVersion": "7.5.1.0",
|
|
||||||
"fileVersion": "7.5.1.50405"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Microsoft.IdentityModel.Tokens/7.5.1": {
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.IdentityModel.Logging": "7.5.1"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/net6.0/Microsoft.IdentityModel.Tokens.dll": {
|
|
||||||
"assemblyVersion": "7.5.1.0",
|
|
||||||
"fileVersion": "7.5.1.50405"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Microsoft.Win32.SystemEvents/7.0.0": {
|
|
||||||
"runtime": {
|
|
||||||
"lib/net7.0/Microsoft.Win32.SystemEvents.dll": {
|
|
||||||
"assemblyVersion": "7.0.0.0",
|
|
||||||
"fileVersion": "7.0.22.51805"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"runtimeTargets": {
|
|
||||||
"runtimes/win/lib/net7.0/Microsoft.Win32.SystemEvents.dll": {
|
|
||||||
"rid": "win",
|
|
||||||
"assetType": "runtime",
|
|
||||||
"assemblyVersion": "7.0.0.0",
|
|
||||||
"fileVersion": "7.0.22.51805"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"System.Configuration.ConfigurationManager/7.0.0": {
|
|
||||||
"dependencies": {
|
|
||||||
"System.Diagnostics.EventLog": "7.0.0",
|
|
||||||
"System.Security.Cryptography.ProtectedData": "7.0.0",
|
|
||||||
"System.Security.Permissions": "7.0.0"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/net7.0/System.Configuration.ConfigurationManager.dll": {
|
|
||||||
"assemblyVersion": "7.0.0.0",
|
|
||||||
"fileVersion": "7.0.22.51805"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"System.Diagnostics.EventLog/7.0.0": {
|
|
||||||
"runtime": {
|
|
||||||
"lib/net7.0/System.Diagnostics.EventLog.dll": {
|
|
||||||
"assemblyVersion": "7.0.0.0",
|
|
||||||
"fileVersion": "7.0.22.51805"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"runtimeTargets": {
|
|
||||||
"runtimes/win/lib/net7.0/System.Diagnostics.EventLog.Messages.dll": {
|
|
||||||
"rid": "win",
|
|
||||||
"assetType": "runtime",
|
|
||||||
"assemblyVersion": "7.0.0.0",
|
|
||||||
"fileVersion": "0.0.0.0"
|
|
||||||
},
|
|
||||||
"runtimes/win/lib/net7.0/System.Diagnostics.EventLog.dll": {
|
|
||||||
"rid": "win",
|
|
||||||
"assetType": "runtime",
|
|
||||||
"assemblyVersion": "7.0.0.0",
|
|
||||||
"fileVersion": "7.0.22.51805"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"System.DirectoryServices/7.0.1": {
|
|
||||||
"dependencies": {
|
|
||||||
"System.Security.Permissions": "7.0.0"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/net7.0/System.DirectoryServices.dll": {
|
|
||||||
"assemblyVersion": "4.0.0.0",
|
|
||||||
"fileVersion": "7.0.323.6910"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"runtimeTargets": {
|
|
||||||
"runtimes/win/lib/net7.0/System.DirectoryServices.dll": {
|
|
||||||
"rid": "win",
|
|
||||||
"assetType": "runtime",
|
|
||||||
"assemblyVersion": "4.0.0.0",
|
|
||||||
"fileVersion": "7.0.323.6910"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"System.DirectoryServices.AccountManagement/7.0.1": {
|
|
||||||
"dependencies": {
|
|
||||||
"System.Configuration.ConfigurationManager": "7.0.0",
|
|
||||||
"System.DirectoryServices": "7.0.1",
|
|
||||||
"System.DirectoryServices.Protocols": "7.0.1"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/net7.0/System.DirectoryServices.AccountManagement.dll": {
|
|
||||||
"assemblyVersion": "4.0.0.0",
|
|
||||||
"fileVersion": "7.0.1123.42427"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"runtimeTargets": {
|
|
||||||
"runtimes/win/lib/net7.0/System.DirectoryServices.AccountManagement.dll": {
|
|
||||||
"rid": "win",
|
|
||||||
"assetType": "runtime",
|
|
||||||
"assemblyVersion": "4.0.0.0",
|
|
||||||
"fileVersion": "7.0.1123.42427"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"System.DirectoryServices.Protocols/7.0.1": {
|
|
||||||
"runtime": {
|
|
||||||
"lib/net7.0/System.DirectoryServices.Protocols.dll": {
|
|
||||||
"assemblyVersion": "7.0.0.1",
|
|
||||||
"fileVersion": "7.0.723.27404"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"runtimeTargets": {
|
|
||||||
"runtimes/linux/lib/net7.0/System.DirectoryServices.Protocols.dll": {
|
|
||||||
"rid": "linux",
|
|
||||||
"assetType": "runtime",
|
|
||||||
"assemblyVersion": "7.0.0.1",
|
|
||||||
"fileVersion": "7.0.723.27404"
|
|
||||||
},
|
|
||||||
"runtimes/osx/lib/net7.0/System.DirectoryServices.Protocols.dll": {
|
|
||||||
"rid": "osx",
|
|
||||||
"assetType": "runtime",
|
|
||||||
"assemblyVersion": "7.0.0.1",
|
|
||||||
"fileVersion": "7.0.723.27404"
|
|
||||||
},
|
|
||||||
"runtimes/win/lib/net7.0/System.DirectoryServices.Protocols.dll": {
|
|
||||||
"rid": "win",
|
|
||||||
"assetType": "runtime",
|
|
||||||
"assemblyVersion": "7.0.0.1",
|
|
||||||
"fileVersion": "7.0.723.27404"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"System.Drawing.Common/7.0.0": {
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.Win32.SystemEvents": "7.0.0"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/net7.0/System.Drawing.Common.dll": {
|
|
||||||
"assemblyVersion": "7.0.0.0",
|
|
||||||
"fileVersion": "7.0.22.51805"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"runtimeTargets": {
|
|
||||||
"runtimes/win/lib/net7.0/System.Drawing.Common.dll": {
|
|
||||||
"rid": "win",
|
|
||||||
"assetType": "runtime",
|
|
||||||
"assemblyVersion": "7.0.0.0",
|
|
||||||
"fileVersion": "7.0.22.51805"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"System.IdentityModel.Tokens.Jwt/7.5.1": {
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.IdentityModel.JsonWebTokens": "7.5.1",
|
|
||||||
"Microsoft.IdentityModel.Tokens": "7.5.1"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/net6.0/System.IdentityModel.Tokens.Jwt.dll": {
|
|
||||||
"assemblyVersion": "7.5.1.0",
|
|
||||||
"fileVersion": "7.5.1.50405"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"System.Security.Cryptography.ProtectedData/7.0.0": {
|
|
||||||
"runtime": {
|
|
||||||
"lib/net7.0/System.Security.Cryptography.ProtectedData.dll": {
|
|
||||||
"assemblyVersion": "7.0.0.0",
|
|
||||||
"fileVersion": "7.0.22.51805"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"runtimeTargets": {
|
|
||||||
"runtimes/win/lib/net7.0/System.Security.Cryptography.ProtectedData.dll": {
|
|
||||||
"rid": "win",
|
|
||||||
"assetType": "runtime",
|
|
||||||
"assemblyVersion": "7.0.0.0",
|
|
||||||
"fileVersion": "7.0.22.51805"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"System.Security.Permissions/7.0.0": {
|
|
||||||
"dependencies": {
|
|
||||||
"System.Windows.Extensions": "7.0.0"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/net7.0/System.Security.Permissions.dll": {
|
|
||||||
"assemblyVersion": "7.0.0.0",
|
|
||||||
"fileVersion": "7.0.22.51805"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"System.Windows.Extensions/7.0.0": {
|
|
||||||
"dependencies": {
|
|
||||||
"System.Drawing.Common": "7.0.0"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/net7.0/System.Windows.Extensions.dll": {
|
|
||||||
"assemblyVersion": "7.0.0.0",
|
|
||||||
"fileVersion": "7.0.22.51805"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"runtimeTargets": {
|
|
||||||
"runtimes/win/lib/net7.0/System.Windows.Extensions.dll": {
|
|
||||||
"rid": "win",
|
|
||||||
"assetType": "runtime",
|
|
||||||
"assemblyVersion": "7.0.0.0",
|
|
||||||
"fileVersion": "7.0.22.51805"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"WebCore.Contracts/1.0.1": {
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.Extensions.Caching.Memory": "7.0.0",
|
|
||||||
"Microsoft.Extensions.Configuration.Binder": "7.0.4",
|
|
||||||
"System.DirectoryServices": "7.0.1",
|
|
||||||
"System.DirectoryServices.AccountManagement": "7.0.1",
|
|
||||||
"System.IdentityModel.Tokens.Jwt": "7.5.1"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"DigitalData.Core.Contracts.dll": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"DigitalData.Core.Contracts/1.0.1.0": {
|
|
||||||
"runtime": {
|
|
||||||
"DigitalData.Core.Contracts.dll": {
|
|
||||||
"assemblyVersion": "1.0.1.0",
|
|
||||||
"fileVersion": "1.0.1.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"libraries": {
|
|
||||||
"DigitalData.Core.CultureServices/1.0.0": {
|
|
||||||
"type": "project",
|
|
||||||
"serviceable": false,
|
|
||||||
"sha512": ""
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Caching.Abstractions/7.0.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-IeimUd0TNbhB4ded3AbgBLQv2SnsiVugDyGV1MvspQFVlA07nDC7Zul7kcwH5jWN3JiTcp/ySE83AIJo8yfKjg==",
|
|
||||||
"path": "microsoft.extensions.caching.abstractions/7.0.0",
|
|
||||||
"hashPath": "microsoft.extensions.caching.abstractions.7.0.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Caching.Memory/7.0.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-xpidBs2KCE2gw1JrD0quHE72kvCaI3xFql5/Peb2GRtUuZX+dYPoK/NTdVMiM67Svym0M0Df9A3xyU0FbMQhHw==",
|
|
||||||
"path": "microsoft.extensions.caching.memory/7.0.0",
|
|
||||||
"hashPath": "microsoft.extensions.caching.memory.7.0.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Configuration.Abstractions/7.0.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-f34u2eaqIjNO9YLHBz8rozVZ+TcFiFs0F3r7nUJd7FRkVSxk8u4OpoK226mi49MwexHOR2ibP9MFvRUaLilcQQ==",
|
|
||||||
"path": "microsoft.extensions.configuration.abstractions/7.0.0",
|
|
||||||
"hashPath": "microsoft.extensions.configuration.abstractions.7.0.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Configuration.Binder/7.0.4": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-8+XPvJnHZsYgHOQlcMuQe7QNF5KdVKHH1F/wW3nd8/u81Gk/XFAYMDP0Lpz18h7/AM95M662vvqMorcYxCBB4w==",
|
|
||||||
"path": "microsoft.extensions.configuration.binder/7.0.4",
|
|
||||||
"hashPath": "microsoft.extensions.configuration.binder.7.0.4.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.DependencyInjection.Abstractions/7.0.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-h3j/QfmFN4S0w4C2A6X7arXij/M/OVw3uQHSOFxnND4DyAzO1F9eMX7Eti7lU/OkSthEE0WzRsfT/Dmx86jzCw==",
|
|
||||||
"path": "microsoft.extensions.dependencyinjection.abstractions/7.0.0",
|
|
||||||
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.7.0.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Localization/7.0.16": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-JpTQ/El4m/Yfup+sgwvp8qtYAoxEYe9wXy63gw/KXep8bzUdA1wfReed0rL2UqR9Uk7hDnjfYFCz190B2fBYdA==",
|
|
||||||
"path": "microsoft.extensions.localization/7.0.16",
|
|
||||||
"hashPath": "microsoft.extensions.localization.7.0.16.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Localization.Abstractions/7.0.16": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-wUwfDVcOMRUZv+zX45Vyh/MkXpdOy7nIvRRf3n2iiYoh76M0Dr/wx8Ppxk3v9H556z2e0QwLVQqqkd+oj+CGRQ==",
|
|
||||||
"path": "microsoft.extensions.localization.abstractions/7.0.16",
|
|
||||||
"hashPath": "microsoft.extensions.localization.abstractions.7.0.16.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Logging.Abstractions/7.0.1": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-pkeBFx0vqMW/A3aUVHh7MPu3WkBhaVlezhSZeb1c9XD0vUReYH1TLFSy5MxJgZfmz5LZzYoErMorlYZiwpOoNA==",
|
|
||||||
"path": "microsoft.extensions.logging.abstractions/7.0.1",
|
|
||||||
"hashPath": "microsoft.extensions.logging.abstractions.7.0.1.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Options/7.0.1": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-pZRDYdN1FpepOIfHU62QoBQ6zdAoTvnjxFfqAzEd9Jhb2dfhA5i6jeTdgGgcgTWFRC7oT0+3XrbQu4LjvgX1Nw==",
|
|
||||||
"path": "microsoft.extensions.options/7.0.1",
|
|
||||||
"hashPath": "microsoft.extensions.options.7.0.1.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Primitives/7.0.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-um1KU5kxcRp3CNuI8o/GrZtD4AIOXDk+RLsytjZ9QPok3ttLUelLKpilVPuaFT3TFjOhSibUAso0odbOaCDj3Q==",
|
|
||||||
"path": "microsoft.extensions.primitives/7.0.0",
|
|
||||||
"hashPath": "microsoft.extensions.primitives.7.0.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"Microsoft.IdentityModel.Abstractions/7.5.1": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-PT16ZFbPIiMsYv07oy3zOjqUOJ7xutGBkJTOX0+IbNyU6+O6X7aIxjq9EaSSRLWbekRgamgtmfg8Xjw6A6Ua9g==",
|
|
||||||
"path": "microsoft.identitymodel.abstractions/7.5.1",
|
|
||||||
"hashPath": "microsoft.identitymodel.abstractions.7.5.1.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"Microsoft.IdentityModel.JsonWebTokens/7.5.1": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-93CGSa8RPdZU8zfvA3nf9NGKUqEnQrE12VzYlMqKh72ddhzusosqLNEUgH/YhFWBLRFOnY1RCgHMV7pR+sAx2w==",
|
|
||||||
"path": "microsoft.identitymodel.jsonwebtokens/7.5.1",
|
|
||||||
"hashPath": "microsoft.identitymodel.jsonwebtokens.7.5.1.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"Microsoft.IdentityModel.Logging/7.5.1": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-PnpAQX20BAiDIPYmWUyQSlEaWD8BLXzHpiDGTCT568Cs0ReOeyzNe401LzCeiv6ilug/KefVeV1CeqtCHTo8dw==",
|
|
||||||
"path": "microsoft.identitymodel.logging/7.5.1",
|
|
||||||
"hashPath": "microsoft.identitymodel.logging.7.5.1.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"Microsoft.IdentityModel.Tokens/7.5.1": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-Q3DKpyFViP84IUlTFKH/zIkswIrmSh2Vd/eFDo4wlOHy4DYxoweZEEw4kDEiKt9VCX6o7SddK3HK2xDYyFpexA==",
|
|
||||||
"path": "microsoft.identitymodel.tokens/7.5.1",
|
|
||||||
"hashPath": "microsoft.identitymodel.tokens.7.5.1.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"Microsoft.Win32.SystemEvents/7.0.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-2nXPrhdAyAzir0gLl8Yy8S5Mnm/uBSQQA7jEsILOS1MTyS7DbmV1NgViMtvV1sfCD1ebITpNwb1NIinKeJgUVQ==",
|
|
||||||
"path": "microsoft.win32.systemevents/7.0.0",
|
|
||||||
"hashPath": "microsoft.win32.systemevents.7.0.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"System.Configuration.ConfigurationManager/7.0.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-WvRUdlL1lB0dTRZSs5XcQOd5q9MYNk90GkbmRmiCvRHThWiojkpGqWdmEDJdXyHbxG/BhE5hmVbMfRLXW9FJVA==",
|
|
||||||
"path": "system.configuration.configurationmanager/7.0.0",
|
|
||||||
"hashPath": "system.configuration.configurationmanager.7.0.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"System.Diagnostics.EventLog/7.0.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-eUDP47obqQm3SFJfP6z+Fx2nJ4KKTQbXB4Q9Uesnzw9SbYdhjyoGXuvDn/gEmFY6N5Z3bFFbpAQGA7m6hrYJCw==",
|
|
||||||
"path": "system.diagnostics.eventlog/7.0.0",
|
|
||||||
"hashPath": "system.diagnostics.eventlog.7.0.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"System.DirectoryServices/7.0.1": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-Z4FVdUJEVXbf7/f/hU6cFZDtxN5ozUVKJMzXoHmC+GCeTcqzlxqmWtxurejxG3K+kZ6H0UKwNshoK1CYnmJ1sg==",
|
|
||||||
"path": "system.directoryservices/7.0.1",
|
|
||||||
"hashPath": "system.directoryservices.7.0.1.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"System.DirectoryServices.AccountManagement/7.0.1": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-UNytHYwA5IF55WQhashsMG57ize83JUGJxD8YJlOyO9ZlMTOD4Nt7y+A6mvmrU/swDoYWaVL+TNwE6hk9lyvbA==",
|
|
||||||
"path": "system.directoryservices.accountmanagement/7.0.1",
|
|
||||||
"hashPath": "system.directoryservices.accountmanagement.7.0.1.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"System.DirectoryServices.Protocols/7.0.1": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-t9hsL+UYRzNs30pnT2Tdx6ngX8McFUjru0a0ekNgu/YXfkXN+dx5OvSEv0/p7H2q3pdJLH7TJPWX7e55J8QB9A==",
|
|
||||||
"path": "system.directoryservices.protocols/7.0.1",
|
|
||||||
"hashPath": "system.directoryservices.protocols.7.0.1.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"System.Drawing.Common/7.0.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-KIX+oBU38pxkKPxvLcLfIkOV5Ien8ReN78wro7OF5/erwcmortzeFx+iBswlh2Vz6gVne0khocQudGwaO1Ey6A==",
|
|
||||||
"path": "system.drawing.common/7.0.0",
|
|
||||||
"hashPath": "system.drawing.common.7.0.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"System.IdentityModel.Tokens.Jwt/7.5.1": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-UUw+E0R73lZLlXgneYIJQxNs1kfbcxjVzw64JQyiwjqCd4HMpAbjn+xRo86QZT84uHq8/MkqvfH82tgjgPzpuw==",
|
|
||||||
"path": "system.identitymodel.tokens.jwt/7.5.1",
|
|
||||||
"hashPath": "system.identitymodel.tokens.jwt.7.5.1.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"System.Security.Cryptography.ProtectedData/7.0.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-xSPiLNlHT6wAHtugASbKAJwV5GVqQK351crnILAucUioFqqieDN79evO1rku1ckt/GfjIn+b17UaSskoY03JuA==",
|
|
||||||
"path": "system.security.cryptography.protecteddata/7.0.0",
|
|
||||||
"hashPath": "system.security.cryptography.protecteddata.7.0.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"System.Security.Permissions/7.0.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-Vmp0iRmCEno9BWiskOW5pxJ3d9n+jUqKxvX4GhLwFhnQaySZmBN2FuC0N5gjFHgyFMUjC5sfIJ8KZfoJwkcMmA==",
|
|
||||||
"path": "system.security.permissions/7.0.0",
|
|
||||||
"hashPath": "system.security.permissions.7.0.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"System.Windows.Extensions/7.0.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-bR4qdCmssMMbo9Fatci49An5B1UaVJZHKNq70PRgzoLYIlitb8Tj7ns/Xt5Pz1CkERiTjcVBDU2y1AVrPBYkaw==",
|
|
||||||
"path": "system.windows.extensions/7.0.0",
|
|
||||||
"hashPath": "system.windows.extensions.7.0.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"WebCore.Contracts/1.0.1": {
|
|
||||||
"type": "project",
|
|
||||||
"serviceable": false,
|
|
||||||
"sha512": ""
|
|
||||||
},
|
|
||||||
"DigitalData.Core.Contracts/1.0.1.0": {
|
|
||||||
"type": "reference",
|
|
||||||
"serviceable": false,
|
|
||||||
"sha512": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 22 KiB |
@@ -1,4 +0,0 @@
|
|||||||
// <autogenerated />
|
|
||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v7.0", FrameworkDisplayName = ".NET 7.0")]
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
// <auto-generated/>
|
|
||||||
global using global::System;
|
|
||||||
global using global::System.Collections.Generic;
|
|
||||||
global using global::System.IO;
|
|
||||||
global using global::System.Linq;
|
|
||||||
global using global::System.Net.Http;
|
|
||||||
global using global::System.Threading;
|
|
||||||
global using global::System.Threading.Tasks;
|
|
||||||
@@ -1,170 +0,0 @@
|
|||||||
{
|
|
||||||
"format": 1,
|
|
||||||
"restore": {
|
|
||||||
"E:\\TekH\\Visual Studio\\WebCoreModules\\DigitalData.Core.CultureServices\\DigitalData.Core.CultureServices.csproj": {}
|
|
||||||
},
|
|
||||||
"projects": {
|
|
||||||
"E:\\TekH\\Visual Studio\\WebCoreModules\\DigitalData.Core.Contracts\\DigitalData.Core.Contracts.csproj": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"restore": {
|
|
||||||
"projectUniqueName": "E:\\TekH\\Visual Studio\\WebCoreModules\\DigitalData.Core.Contracts\\DigitalData.Core.Contracts.csproj",
|
|
||||||
"projectName": "WebCore.Contracts",
|
|
||||||
"projectPath": "E:\\TekH\\Visual Studio\\WebCoreModules\\DigitalData.Core.Contracts\\DigitalData.Core.Contracts.csproj",
|
|
||||||
"packagesPath": "C:\\Users\\tekh\\.nuget\\packages\\",
|
|
||||||
"outputPath": "E:\\TekH\\Visual Studio\\WebCoreModules\\DigitalData.Core.Contracts\\obj\\",
|
|
||||||
"projectStyle": "PackageReference",
|
|
||||||
"fallbackFolders": [
|
|
||||||
"D:\\ProgramFiles\\DevExpress 21.2\\Components\\Offline Packages"
|
|
||||||
],
|
|
||||||
"configFilePaths": [
|
|
||||||
"C:\\Users\\tekh\\AppData\\Roaming\\NuGet\\NuGet.Config",
|
|
||||||
"C:\\Program Files (x86)\\NuGet\\Config\\DevExpress 21.2.config",
|
|
||||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
|
|
||||||
],
|
|
||||||
"originalTargetFrameworks": [
|
|
||||||
"net7.0"
|
|
||||||
],
|
|
||||||
"sources": {
|
|
||||||
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
|
|
||||||
"D:\\ProgramFiles\\DevExpress 21.2\\Components\\System\\Components\\Packages": {},
|
|
||||||
"https://api.nuget.org/v3/index.json": {}
|
|
||||||
},
|
|
||||||
"frameworks": {
|
|
||||||
"net7.0": {
|
|
||||||
"targetAlias": "net7.0",
|
|
||||||
"projectReferences": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"warningProperties": {
|
|
||||||
"warnAsError": [
|
|
||||||
"NU1605"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"restoreAuditProperties": {
|
|
||||||
"enableAudit": "true",
|
|
||||||
"auditLevel": "low",
|
|
||||||
"auditMode": "direct"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"frameworks": {
|
|
||||||
"net7.0": {
|
|
||||||
"targetAlias": "net7.0",
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.Extensions.Caching.Memory": {
|
|
||||||
"target": "Package",
|
|
||||||
"version": "[7.0.0, )"
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Configuration.Binder": {
|
|
||||||
"target": "Package",
|
|
||||||
"version": "[7.0.4, )"
|
|
||||||
},
|
|
||||||
"System.DirectoryServices": {
|
|
||||||
"target": "Package",
|
|
||||||
"version": "[7.0.1, )"
|
|
||||||
},
|
|
||||||
"System.DirectoryServices.AccountManagement": {
|
|
||||||
"target": "Package",
|
|
||||||
"version": "[7.0.1, )"
|
|
||||||
},
|
|
||||||
"System.IdentityModel.Tokens.Jwt": {
|
|
||||||
"target": "Package",
|
|
||||||
"version": "[7.5.1, )"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"imports": [
|
|
||||||
"net461",
|
|
||||||
"net462",
|
|
||||||
"net47",
|
|
||||||
"net471",
|
|
||||||
"net472",
|
|
||||||
"net48",
|
|
||||||
"net481"
|
|
||||||
],
|
|
||||||
"assetTargetFallback": true,
|
|
||||||
"warn": true,
|
|
||||||
"frameworkReferences": {
|
|
||||||
"Microsoft.NETCore.App": {
|
|
||||||
"privateAssets": "all"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\8.0.200\\RuntimeIdentifierGraph.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"E:\\TekH\\Visual Studio\\WebCoreModules\\DigitalData.Core.CultureServices\\DigitalData.Core.CultureServices.csproj": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"restore": {
|
|
||||||
"projectUniqueName": "E:\\TekH\\Visual Studio\\WebCoreModules\\DigitalData.Core.CultureServices\\DigitalData.Core.CultureServices.csproj",
|
|
||||||
"projectName": "DigitalData.Core.CultureServices",
|
|
||||||
"projectPath": "E:\\TekH\\Visual Studio\\WebCoreModules\\DigitalData.Core.CultureServices\\DigitalData.Core.CultureServices.csproj",
|
|
||||||
"packagesPath": "C:\\Users\\tekh\\.nuget\\packages\\",
|
|
||||||
"outputPath": "E:\\TekH\\Visual Studio\\WebCoreModules\\DigitalData.Core.CultureServices\\obj\\",
|
|
||||||
"projectStyle": "PackageReference",
|
|
||||||
"fallbackFolders": [
|
|
||||||
"D:\\ProgramFiles\\DevExpress 21.2\\Components\\Offline Packages"
|
|
||||||
],
|
|
||||||
"configFilePaths": [
|
|
||||||
"C:\\Users\\tekh\\AppData\\Roaming\\NuGet\\NuGet.Config",
|
|
||||||
"C:\\Program Files (x86)\\NuGet\\Config\\DevExpress 21.2.config",
|
|
||||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
|
|
||||||
],
|
|
||||||
"originalTargetFrameworks": [
|
|
||||||
"net7.0"
|
|
||||||
],
|
|
||||||
"sources": {
|
|
||||||
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
|
|
||||||
"D:\\ProgramFiles\\DevExpress 21.2\\Components\\System\\Components\\Packages": {},
|
|
||||||
"https://api.nuget.org/v3/index.json": {}
|
|
||||||
},
|
|
||||||
"frameworks": {
|
|
||||||
"net7.0": {
|
|
||||||
"targetAlias": "net7.0",
|
|
||||||
"projectReferences": {
|
|
||||||
"E:\\TekH\\Visual Studio\\WebCoreModules\\DigitalData.Core.Contracts\\DigitalData.Core.Contracts.csproj": {
|
|
||||||
"projectPath": "E:\\TekH\\Visual Studio\\WebCoreModules\\DigitalData.Core.Contracts\\DigitalData.Core.Contracts.csproj"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"warningProperties": {
|
|
||||||
"warnAsError": [
|
|
||||||
"NU1605"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"restoreAuditProperties": {
|
|
||||||
"enableAudit": "true",
|
|
||||||
"auditLevel": "low",
|
|
||||||
"auditMode": "direct"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"frameworks": {
|
|
||||||
"net7.0": {
|
|
||||||
"targetAlias": "net7.0",
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.Extensions.Localization": {
|
|
||||||
"target": "Package",
|
|
||||||
"version": "[7.0.16, )"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"imports": [
|
|
||||||
"net461",
|
|
||||||
"net462",
|
|
||||||
"net47",
|
|
||||||
"net471",
|
|
||||||
"net472",
|
|
||||||
"net48",
|
|
||||||
"net481"
|
|
||||||
],
|
|
||||||
"assetTargetFallback": true,
|
|
||||||
"warn": true,
|
|
||||||
"frameworkReferences": {
|
|
||||||
"Microsoft.NETCore.App": {
|
|
||||||
"privateAssets": "all"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\8.0.200\\RuntimeIdentifierGraph.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
|
||||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
|
||||||
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
|
|
||||||
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
|
|
||||||
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
|
|
||||||
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
|
|
||||||
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\tekh\.nuget\packages\;D:\ProgramFiles\DevExpress 21.2\Components\Offline Packages</NuGetPackageFolders>
|
|
||||||
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
|
|
||||||
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.9.1</NuGetToolVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
|
||||||
<SourceRoot Include="C:\Users\tekh\.nuget\packages\" />
|
|
||||||
<SourceRoot Include="D:\ProgramFiles\DevExpress 21.2\Components\Offline Packages\" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
|
||||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
|
||||||
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\7.0.1\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\7.0.1\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets')" />
|
|
||||||
</ImportGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
|
||||||
<metadata>
|
|
||||||
<id>DigitalData.Core.CultureServices</id>
|
|
||||||
<version>1.0.0</version>
|
|
||||||
<authors>DigitalData.Core.CultureServices</authors>
|
|
||||||
<description>Package Description</description>
|
|
||||||
<repository type="git" commit="82da3586a5e28ae5fbd4242f05f60f9e5327e5f2" />
|
|
||||||
<dependencies>
|
|
||||||
<group targetFramework="net7.0">
|
|
||||||
<dependency id="WebCore.Contracts" version="1.0.1" exclude="Build,Analyzers" />
|
|
||||||
<dependency id="Microsoft.Extensions.Localization" version="7.0.16" exclude="Build,Analyzers" />
|
|
||||||
</group>
|
|
||||||
</dependencies>
|
|
||||||
</metadata>
|
|
||||||
<files>
|
|
||||||
<file src="E:\TekH\Visual Studio\WebCoreModules\DigitalData.Core.CultureServices\bin\Release\net7.0\DigitalData.Core.CultureServices.dll" target="lib\net7.0\DigitalData.Core.CultureServices.dll" />
|
|
||||||
</files>
|
|
||||||
</package>
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
// <autogenerated />
|
|
||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v7.0", FrameworkDisplayName = ".NET 7.0")]
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
is_global = true
|
|
||||||
build_property.TargetFramework = net7.0
|
|
||||||
build_property.TargetPlatformMinVersion =
|
|
||||||
build_property.UsingMicrosoftNETSdkWeb =
|
|
||||||
build_property.ProjectTypeGuids =
|
|
||||||
build_property.InvariantGlobalization =
|
|
||||||
build_property.PlatformNeutralAssembly =
|
|
||||||
build_property.EnforceExtendedAnalyzerRules =
|
|
||||||
build_property._SupportedPlatformList = Linux,macOS,Windows
|
|
||||||
build_property.RootNamespace = DigitalData.Core.CultureServices
|
|
||||||
build_property.ProjectDir = E:\TekH\Visual Studio\WebCoreModules\DigitalData.Core.CultureServices\
|
|
||||||
build_property.EnableComHosting =
|
|
||||||
build_property.EnableGeneratedComInterfaceComImportInterop =
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
// <auto-generated/>
|
|
||||||
global using global::System;
|
|
||||||
global using global::System.Collections.Generic;
|
|
||||||
global using global::System.IO;
|
|
||||||
global using global::System.Linq;
|
|
||||||
global using global::System.Net.Http;
|
|
||||||
global using global::System.Threading;
|
|
||||||
global using global::System.Threading.Tasks;
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
36fef0fd26a832d2188715455582d92b1504d333459c8ca9de1908bace5726e0
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
E:\TekH\Visual Studio\WebCoreModules\DigitalData.Core.CultureServices\bin\Release\net7.0\DigitalData.Core.CultureServices.deps.json
|
|
||||||
E:\TekH\Visual Studio\WebCoreModules\DigitalData.Core.CultureServices\bin\Release\net7.0\DigitalData.Core.CultureServices.dll
|
|
||||||
E:\TekH\Visual Studio\WebCoreModules\DigitalData.Core.CultureServices\bin\Release\net7.0\DigitalData.Core.CultureServices.pdb
|
|
||||||
E:\TekH\Visual Studio\WebCoreModules\DigitalData.Core.CultureServices\bin\Release\net7.0\DigitalData.Core.Contracts.dll
|
|
||||||
E:\TekH\Visual Studio\WebCoreModules\DigitalData.Core.CultureServices\bin\Release\net7.0\DigitalData.Core.Contracts.pdb
|
|
||||||
E:\TekH\Visual Studio\WebCoreModules\DigitalData.Core.CultureServices\obj\Release\net7.0\DigitalData.Core.CultureServices.csproj.AssemblyReference.cache
|
|
||||||
E:\TekH\Visual Studio\WebCoreModules\DigitalData.Core.CultureServices\obj\Release\net7.0\DigitalData.Core.CultureServices.GeneratedMSBuildEditorConfig.editorconfig
|
|
||||||
E:\TekH\Visual Studio\WebCoreModules\DigitalData.Core.CultureServices\obj\Release\net7.0\DigitalData.Core.CultureServices.AssemblyInfoInputs.cache
|
|
||||||
E:\TekH\Visual Studio\WebCoreModules\DigitalData.Core.CultureServices\obj\Release\net7.0\DigitalData.Core.CultureServices.AssemblyInfo.cs
|
|
||||||
E:\TekH\Visual Studio\WebCoreModules\DigitalData.Core.CultureServices\obj\Release\net7.0\DigitalData.Core.CultureServices.csproj.CoreCompileInputs.cache
|
|
||||||
E:\TekH\Visual Studio\WebCoreModules\DigitalData.Core.CultureServices\obj\Release\net7.0\DigitalD.489AA3D4.Up2Date
|
|
||||||
E:\TekH\Visual Studio\WebCoreModules\DigitalData.Core.CultureServices\obj\Release\net7.0\DigitalData.Core.CultureServices.dll
|
|
||||||
E:\TekH\Visual Studio\WebCoreModules\DigitalData.Core.CultureServices\obj\Release\net7.0\refint\DigitalData.Core.CultureServices.dll
|
|
||||||
E:\TekH\Visual Studio\WebCoreModules\DigitalData.Core.CultureServices\obj\Release\net7.0\DigitalData.Core.CultureServices.pdb
|
|
||||||
E:\TekH\Visual Studio\WebCoreModules\DigitalData.Core.CultureServices\obj\Release\net7.0\ref\DigitalData.Core.CultureServices.dll
|
|
||||||
E:\TekH\Visual Studio\WebCoreModules\DigitalData.Core.CultureServices\bin\Release\net7.0\icon.png
|
|
||||||
|
Before Width: | Height: | Size: 1020 KiB |
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<Description>This package provides Data Transfer Object (DTO) implementations and related utilities. It includes generic result handling, DTO extension methods, cookie consent settings management, and AutoMapper integration for robust object mapping, all adhering to Clean Architecture principles to ensure separation of concerns and maintainability.</Description>
|
<Description>This package provides Data Transfer Object (DTO) implementations and related utilities. It includes generic result handling, DTO extension methods, cookie consent settings management, and AutoMapper integration for robust object mapping, all adhering to Clean Architecture principles to ensure separation of concerns and maintainability.</Description>
|
||||||
@@ -12,13 +12,13 @@
|
|||||||
<Company>Digital Data GmbH</Company>
|
<Company>Digital Data GmbH</Company>
|
||||||
<Product>DigitalData.Core.DTO</Product>
|
<Product>DigitalData.Core.DTO</Product>
|
||||||
<Copyright>Copyright 2024</Copyright>
|
<Copyright>Copyright 2024</Copyright>
|
||||||
<PackageIcon>icon.png</PackageIcon>
|
<PackageIcon>core_icon.png</PackageIcon>
|
||||||
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
|
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
|
||||||
<PackageTags>digital data core dto clean architecture result pattern</PackageTags>
|
<PackageTags>digital data core dto clean architecture result pattern</PackageTags>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\DigitalData.Core.Abstractions\Assets\icon.png">
|
<None Include="..\..\nuget-package-icons\core_icon.png">
|
||||||
<Pack>True</Pack>
|
<Pack>True</Pack>
|
||||||
<PackagePath>\</PackagePath>
|
<PackagePath>\</PackagePath>
|
||||||
</None>
|
</None>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1020 KiB |
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||||
@@ -12,14 +12,14 @@
|
|||||||
<Product>DigitalData.Core.Infrastructure</Product>
|
<Product>DigitalData.Core.Infrastructure</Product>
|
||||||
<Description>This package provides implementations for data access and other low-level services within the DigitalData.Core.Abstractions library. It includes generic CRUD operations using Entity Framework Core, database context management, and other infrastructure-related functionalities, adhering to Clean Architecture principles to ensure separation of concerns and maintainability.</Description>
|
<Description>This package provides implementations for data access and other low-level services within the DigitalData.Core.Abstractions library. It includes generic CRUD operations using Entity Framework Core, database context management, and other infrastructure-related functionalities, adhering to Clean Architecture principles to ensure separation of concerns and maintainability.</Description>
|
||||||
<Copyright>Copyright 2024</Copyright>
|
<Copyright>Copyright 2024</Copyright>
|
||||||
<PackageIcon>icon.png</PackageIcon>
|
<PackageIcon>core_icon.png</PackageIcon>
|
||||||
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
|
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
|
||||||
<RepositoryType>digital data core abstractions clean architecture</RepositoryType>
|
<RepositoryType>digital data core abstractions clean architecture</RepositoryType>
|
||||||
<PackageTags>digital data core infrastructure clean architecture</PackageTags>
|
<PackageTags>digital data core infrastructure clean architecture</PackageTags>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\DigitalData.Core.Abstractions\Assets\icon.png">
|
<None Include="..\..\nuget-package-icons\core_icon.png">
|
||||||
<Pack>True</Pack>
|
<Pack>True</Pack>
|
||||||
<PackagePath>\</PackagePath>
|
<PackagePath>\</PackagePath>
|
||||||
</None>
|
</None>
|
||||||
|
|||||||
@@ -13,7 +13,10 @@
|
|||||||
<SourceRoot Include="C:\Users\tekh\.nuget\packages\" />
|
<SourceRoot Include="C:\Users\tekh\.nuget\packages\" />
|
||||||
<SourceRoot Include="D:\ProgramFiles\DevExpress 21.2\Components\Offline Packages\" />
|
<SourceRoot Include="D:\ProgramFiles\DevExpress 21.2\Components\Offline Packages\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
<ImportGroup Condition=" '$(TargetFramework)' == 'net7.0' AND '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||||
|
<Import Project="$(NuGetPackageRoot)microsoft.entityframeworkcore\7.0.16\buildTransitive\net6.0\Microsoft.EntityFrameworkCore.props" Condition="Exists('$(NuGetPackageRoot)microsoft.entityframeworkcore\7.0.16\buildTransitive\net6.0\Microsoft.EntityFrameworkCore.props')" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition=" '$(TargetFramework)' == 'net8.0' AND '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||||
<Import Project="$(NuGetPackageRoot)microsoft.entityframeworkcore\7.0.16\buildTransitive\net6.0\Microsoft.EntityFrameworkCore.props" Condition="Exists('$(NuGetPackageRoot)microsoft.entityframeworkcore\7.0.16\buildTransitive\net6.0\Microsoft.EntityFrameworkCore.props')" />
|
<Import Project="$(NuGetPackageRoot)microsoft.entityframeworkcore\7.0.16\buildTransitive\net6.0\Microsoft.EntityFrameworkCore.props" Condition="Exists('$(NuGetPackageRoot)microsoft.entityframeworkcore\7.0.16\buildTransitive\net6.0\Microsoft.EntityFrameworkCore.props')" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
<ImportGroup Condition=" '$(TargetFramework)' == 'net7.0' AND '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||||
|
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\7.0.0\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\7.0.0\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets')" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition=" '$(TargetFramework)' == 'net8.0' AND '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||||
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\7.0.0\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\7.0.0\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets')" />
|
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\7.0.0\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\7.0.0\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets')" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
</Project>
|
</Project>
|
||||||
11
DigitalData.Core.Security/Config/ClaimDescriptor.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
using System.Security.Claims;
|
||||||
|
|
||||||
|
namespace DigitalData.Core.Security.Config
|
||||||
|
{
|
||||||
|
public class ClaimDescriptor<TPrincipal>
|
||||||
|
{
|
||||||
|
public Func<TPrincipal, IDictionary<string, object>>? CreateClaims { get; init; }
|
||||||
|
|
||||||
|
public Func<TPrincipal, ClaimsIdentity>? CreateSubject { get; init; }
|
||||||
|
}
|
||||||
|
}
|
||||||
104
DigitalData.Core.Security/Config/CryptoFactoryParams.cs
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
using DigitalData.Core.Security.RSAKey;
|
||||||
|
|
||||||
|
namespace DigitalData.Core.Security.Config
|
||||||
|
{
|
||||||
|
public class CryptoFactoryParams : RSAFactoryParams
|
||||||
|
{
|
||||||
|
public string PemDirectory { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the separator used to concatenate the components of a file-related token string.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The resulting file-related token string is constructed as follows:
|
||||||
|
/// <c>string.Join(FileNameSeparator, Issuer, Audience, Secret_version)</c>.
|
||||||
|
/// If <c>Secret_version</c> is not null, it will be included in the concatenation.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// For example, if <c>FileNameSeparator = "_-_"</c>, the output might look like:
|
||||||
|
/// <c>"Issuer_-_Audience_-_Secret_version"</c>.
|
||||||
|
/// </example>
|
||||||
|
public string FileNameSeparator { get; init; } = "_-_";
|
||||||
|
|
||||||
|
public string FileExtension { get; init; } = "pem";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///This is the subtext of the pem file name. For the file to be automatically renewed, the name must be assigned to change periodically. For example, by default MM/2 will be refreshed every 2 months.
|
||||||
|
/// <br />
|
||||||
|
/// - <see cref="StringExtensions.ToTag(DateTime, string)" /> is used when converting to tag.
|
||||||
|
/// <br />
|
||||||
|
/// - If the format contains the symbol “//”, the method divides the numeric value obtained from the left side of the format
|
||||||
|
/// by one minus the numeric value obtained from the right side of the format string and adds one. For instance:
|
||||||
|
/// <br />
|
||||||
|
/// - If the date is 02.03.2024 and the format is "MM//2", it extracts the month (02), subtracts one (3), divides it by 2,
|
||||||
|
/// rounds down the outgoing number (1), adds one to the number (resulting in 2).
|
||||||
|
/// <br />
|
||||||
|
/// - If the format does not contain "//", the method uses the default <see cref="DateTime.ToString"/> format.
|
||||||
|
/// <br />
|
||||||
|
/// This method provides a way to format the date based on typical or customized rules, including mathematical operations like division.
|
||||||
|
/// </summary>
|
||||||
|
public string DateTagFormat { get; init; } = "MM//2";
|
||||||
|
|
||||||
|
public IEnumerable<RSADecryptor> Decryptors { get; init; } = new List<RSADecryptor>();
|
||||||
|
|
||||||
|
public IEnumerable<RSATokenDescriptor> TokenDescriptors { get; init; } = new List<RSATokenDescriptor>();
|
||||||
|
|
||||||
|
public RSADecryptor? VaultDecryptor { get; init; }
|
||||||
|
|
||||||
|
public CryptoFactoryParams()
|
||||||
|
{
|
||||||
|
// init decryptors
|
||||||
|
AfterCreate += () =>
|
||||||
|
{
|
||||||
|
// Create root folder if it does not exist
|
||||||
|
if (!Directory.Exists(PemDirectory))
|
||||||
|
Directory.CreateDirectory(PemDirectory);
|
||||||
|
|
||||||
|
var privateKeys = new List<RSAPrivateKey>();
|
||||||
|
privateKeys.AddRange(Decryptors);
|
||||||
|
privateKeys.AddRange(TokenDescriptors);
|
||||||
|
if (VaultDecryptor is not null)
|
||||||
|
privateKeys.Add(VaultDecryptor);
|
||||||
|
|
||||||
|
foreach (var privateKey in privateKeys)
|
||||||
|
{
|
||||||
|
// set default path
|
||||||
|
if (privateKey.IsPemNull)
|
||||||
|
{
|
||||||
|
// file name
|
||||||
|
var file_name_params = new List<object>();
|
||||||
|
|
||||||
|
if (privateKey.Id is not null)
|
||||||
|
file_name_params.Add(privateKey.Id);
|
||||||
|
else if (privateKey is RSATokenDescriptor descriptor)
|
||||||
|
file_name_params.Add(descriptor.Issuer);
|
||||||
|
|
||||||
|
file_name_params.Add(KeySizeInBits);
|
||||||
|
file_name_params.Add(DateTime.Now.ToTag(DateTagFormat));
|
||||||
|
|
||||||
|
if (privateKey.IsEncrypted)
|
||||||
|
file_name_params.Add(Secrets.Version);
|
||||||
|
|
||||||
|
var file_name = $"{string.Join(FileNameSeparator, file_name_params)}.{FileExtension}";
|
||||||
|
|
||||||
|
var path = Path.Combine(PemDirectory, file_name);
|
||||||
|
|
||||||
|
if (File.Exists(path))
|
||||||
|
privateKey.SetPem(File.ReadAllText(path));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var pem = privateKey.IsEncrypted
|
||||||
|
? Instance.RSAFactory.CreateEncryptedPrivateKeyPem(pbeParameters: PbeParameters, keySizeInBits: KeySizeInBits, password: Secrets.PBE_PASSWORD)
|
||||||
|
: Instance.RSAFactory.CreatePrivateKeyPem(keySizeInBits: KeySizeInBits);
|
||||||
|
|
||||||
|
privateKey.SetPem(pem);
|
||||||
|
|
||||||
|
// Save file in background
|
||||||
|
Task.Run(async () => await File.WriteAllTextAsync(path: path, pem));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
DigitalData.Core.Security/Config/MappingProfile.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using AutoMapper;
|
||||||
|
using DigitalData.Core.Abstractions.Security;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
|
||||||
|
namespace DigitalData.Core.Security.Config
|
||||||
|
{
|
||||||
|
public class MappingProfile : Profile
|
||||||
|
{
|
||||||
|
public MappingProfile()
|
||||||
|
{
|
||||||
|
CreateMap<IAsymmetricTokenDescriptor, SecurityTokenDescriptor>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
namespace DigitalData.Core.Security.Config
|
||||||
|
{
|
||||||
|
public class ParamsConfigureOptions<TParams> : IConfigureOptions<TParams> where TParams : RSAFactoryParams
|
||||||
|
{
|
||||||
|
public void Configure(TParams options) => options.Init();
|
||||||
|
}
|
||||||
|
}
|
||||||
59
DigitalData.Core.Security/Config/RSAFactoryParams.cs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace DigitalData.Core.Security.Config
|
||||||
|
{
|
||||||
|
public class RSAFactoryParams : IJsonOnDeserialized
|
||||||
|
{
|
||||||
|
public int KeySizeInBits { get; init; } = 2048;
|
||||||
|
|
||||||
|
public string PbePassword { internal get; init; } = Secrets.PBE_PASSWORD;
|
||||||
|
|
||||||
|
public PbeEncryptionAlgorithm PbeEncryptionAlgorithm { get; init; } = PbeEncryptionAlgorithm.Aes256Cbc;
|
||||||
|
|
||||||
|
public HashAlgorithmName PbeHashAlgorithm { get; init; } = HashAlgorithmName.SHA256;
|
||||||
|
|
||||||
|
// TODO: add as json converter to IConfigurIConfiguration.Config
|
||||||
|
public string PbeHashAlgorithmName
|
||||||
|
{
|
||||||
|
get => PbeHashAlgorithm.ToString();
|
||||||
|
init => PbeHashAlgorithm = (typeof(HashAlgorithmName).GetProperty(value, BindingFlags.Public | BindingFlags.Static)?.GetValue(null) is HashAlgorithmName hashAlgorithmName)
|
||||||
|
? hashAlgorithmName
|
||||||
|
: new(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int PbeIterationCount { get; init; } = 100_000;
|
||||||
|
|
||||||
|
public string EncryptedPrivateKeyPemLabel { get; init; } = "ENCRYPTED PRIVATE KEY";
|
||||||
|
|
||||||
|
private PbeParameters? _pbeParameters;
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public PbeParameters PbeParameters => _pbeParameters!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides a thread-safe initialization mechanism using Lazy initialization.
|
||||||
|
/// </summary>
|
||||||
|
private readonly Lazy<bool> _lazyInitializer;
|
||||||
|
|
||||||
|
public bool IsInitialized => _lazyInitializer.IsValueCreated;
|
||||||
|
|
||||||
|
public RSAFactoryParams()
|
||||||
|
{
|
||||||
|
_lazyInitializer = new(() =>
|
||||||
|
{
|
||||||
|
AfterCreate?.Invoke();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
AfterCreate += () => _pbeParameters = new PbeParameters(PbeEncryptionAlgorithm, PbeHashAlgorithm, PbeIterationCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected event Action AfterCreate;
|
||||||
|
|
||||||
|
public void Init() => _ = _lazyInitializer.Value;
|
||||||
|
|
||||||
|
public void OnDeserialized() => Init();
|
||||||
|
}
|
||||||
|
}
|
||||||
38
DigitalData.Core.Security/CryptoFactory.cs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
using DigitalData.Core.Abstractions.Security;
|
||||||
|
using DigitalData.Core.Security.Config;
|
||||||
|
using DigitalData.Core.Security.RSAKey;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
namespace DigitalData.Core.Security
|
||||||
|
{
|
||||||
|
public class CryptoFactory : RSAFactory<CryptoFactoryParams>, ICryptoFactory, IAsymmetricKeyFactory
|
||||||
|
{
|
||||||
|
public IEnumerable<IAsymmetricDecryptor> Decryptors { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// It is a separate decryptor for permanently stored encrypted data. It is assigned to the first Default decryptor by default.
|
||||||
|
/// </summary>
|
||||||
|
public IAsymmetricDecryptor VaultDecryptor { get; }
|
||||||
|
|
||||||
|
public IEnumerable<IAsymmetricTokenDescriptor> TokenDescriptors { get; init; } = new List<IAsymmetricTokenDescriptor>();
|
||||||
|
|
||||||
|
public CryptoFactory(IOptions<CryptoFactoryParams> options, ILogger<CryptoFactory>? logger = null) : base(options)
|
||||||
|
{
|
||||||
|
logger?.LogInformation("Core.Secrets version: {Version}, Created on: {CreationDate}.", Secrets.Version, Secrets.CreationDate.ToString("dd.MM.yyyy"));
|
||||||
|
|
||||||
|
if (!_params.Decryptors.Any())
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
"Any decryptor is not found. Ensure that at least one decryptor is configured in the provided parameters. " +
|
||||||
|
"This issue typically arises if the configuration for decryptors is incomplete or missing. " +
|
||||||
|
"Check the 'Decryptors' collection in the configuration and verify that it contains valid entries."
|
||||||
|
);
|
||||||
|
|
||||||
|
Decryptors = _params.Decryptors;
|
||||||
|
|
||||||
|
TokenDescriptors = _params.TokenDescriptors;
|
||||||
|
|
||||||
|
VaultDecryptor = _params.VaultDecryptor ?? Decryptors.First();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
71
DigitalData.Core.Security/DIExtensions.cs
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
using DigitalData.Core.Abstractions.Security;
|
||||||
|
using DigitalData.Core.Security.Config;
|
||||||
|
using DigitalData.Core.Security.RSAKey;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using System.Security.Claims;
|
||||||
|
|
||||||
|
namespace DigitalData.Core.Security
|
||||||
|
{
|
||||||
|
public static class DIExtensions
|
||||||
|
{
|
||||||
|
private static IServiceCollection AddParamsConfigureOptions<TParams>(this IServiceCollection services) where TParams : RSAFactoryParams
|
||||||
|
=> services.AddSingleton<IConfigureOptions<TParams>, ParamsConfigureOptions<TParams>>();
|
||||||
|
|
||||||
|
private static IServiceCollection AddCryptoFactory(this IServiceCollection services) => services
|
||||||
|
.AddParamsConfigureOptions<CryptoFactoryParams>()
|
||||||
|
.AddAutoMapper(typeof(MappingProfile).Assembly)
|
||||||
|
.AddSingleton<ICryptoFactory, CryptoFactory>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers a custom asym crypt service with specified parameters from the given configuration section.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="services"></param>
|
||||||
|
/// <param name="section"></param>
|
||||||
|
/// <returns>The updated <see cref="IServiceCollection"/> with the RSA Factory registered.</returns>
|
||||||
|
public static IServiceCollection AddCryptoFactory(this IServiceCollection services, IConfigurationSection section) => services
|
||||||
|
.Configure<CryptoFactoryParams>(section)
|
||||||
|
.AddCryptoFactory();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers an asym crypt service with the specified parameters from the given instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="services"></param>
|
||||||
|
/// <returns>The updated <see cref="IServiceCollection"/> with the RSA Factory registered.</returns>
|
||||||
|
public static IServiceCollection AddCryptoFactory(this IServiceCollection services, CryptoFactoryParams? factoryParams = null) => services
|
||||||
|
.AddSingleton(Options.Create(factoryParams ?? new()))
|
||||||
|
.AddCryptoFactory();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers a custom RSA Factory with specified parameters from the given configuration section.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="services"></param>
|
||||||
|
/// <param name="section"></param>
|
||||||
|
/// <returns>The updated <see cref="IServiceCollection"/> with the RSA Factory registered.</returns>
|
||||||
|
public static IServiceCollection AddRSAFactory(this IServiceCollection services, IConfigurationSection section) => services
|
||||||
|
.AddParamsConfigureOptions<RSAFactoryParams>()
|
||||||
|
.Configure<RSAFactoryParams>(section)
|
||||||
|
.AddSingleton<IAsymmetricKeyFactory, RSAFactory<RSAFactoryParams>>();
|
||||||
|
|
||||||
|
private static IServiceCollection AddClaimDescriptor<TPrincipal>(this IServiceCollection services,
|
||||||
|
Func<TPrincipal, IDictionary<string, object>>? claimsMapper = null,
|
||||||
|
Func<TPrincipal, ClaimsIdentity>? subjectMapper = null)
|
||||||
|
{
|
||||||
|
var descriptor = new ClaimDescriptor<TPrincipal>
|
||||||
|
{
|
||||||
|
CreateClaims = claimsMapper,
|
||||||
|
CreateSubject = subjectMapper
|
||||||
|
};
|
||||||
|
|
||||||
|
return services.AddSingleton(sp => Options.Create(descriptor));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IServiceCollection AddJwtSignatureHandler<TPrincipal>(this IServiceCollection services,
|
||||||
|
Func<TPrincipal, IDictionary<string, object>>? claimsMapper = null,
|
||||||
|
Func<TPrincipal, ClaimsIdentity>? subjectMapper = null)
|
||||||
|
=> services
|
||||||
|
.AddClaimDescriptor(claimsMapper: claimsMapper, subjectMapper: subjectMapper)
|
||||||
|
.AddSingleton<IJwtSignatureHandler<TPrincipal>, JwtSignatureHandler<TPrincipal>>();
|
||||||
|
}
|
||||||
|
}
|
||||||
38
DigitalData.Core.Security/DigitalData.Core.Security.csproj
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<PackageId>DigitalData.Core.Security</PackageId>
|
||||||
|
<Version>1.0.0</Version>
|
||||||
|
<Company>Digital Data GmbH</Company>
|
||||||
|
<Product>Digital Data GmbH</Product>
|
||||||
|
<Description>This package provides RSA-based security functionalities as an implementation of the DigitalData.Core.Abstractions.Security library. It supports robust encryption and decryption operations, as well as JWT signing and validation for secure authentication and data integrity.</Description>
|
||||||
|
<Authors>Digital Data GmbH</Authors>
|
||||||
|
<Copyright>Copyright 2025</Copyright>
|
||||||
|
<PackageProjectUrl></PackageProjectUrl>
|
||||||
|
<PackageIcon>core_icon.png</PackageIcon>
|
||||||
|
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
|
||||||
|
<PackageTags>digital data core security</PackageTags>
|
||||||
|
<AssemblyVersion>1.0.0</AssemblyVersion>
|
||||||
|
<FileVersion>1.0.0</FileVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="..\..\nuget-package-icons\core_icon.png">
|
||||||
|
<Pack>True</Pack>
|
||||||
|
<PackagePath>\</PackagePath>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="AutoMapper" Version="13.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\DigitalData.Core.Abstractions\DigitalData.Core.Abstractions.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
89
DigitalData.Core.Security/Extension.cs
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
using AutoMapper;
|
||||||
|
using DigitalData.Core.Abstractions.Security;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
|
||||||
|
namespace DigitalData.Core.Security
|
||||||
|
{
|
||||||
|
internal static class Extension
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a <see cref="DateTime"/> to a formatted string based on the specified format string.
|
||||||
|
/// <br />
|
||||||
|
/// - If the format contains the symbol “//”, the method divides the numeric value obtained from the left side of the format
|
||||||
|
/// by one minus the numeric value obtained from the right side of the format string and adds one. For instance:
|
||||||
|
/// <br />
|
||||||
|
/// - If the date is 02.03.2024 and the format is "MM//2", it extracts the month (02), subtracts one (3), divides it by 2,
|
||||||
|
/// rounds down the outgoing number (1), adds one to the number (resulting in 2).
|
||||||
|
/// <br />
|
||||||
|
/// - If the format does not contain "//", the method uses the default <see cref="DateTime.ToString"/> format.
|
||||||
|
/// <br />
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="date">The <see cref="DateTime"/> value to be formatted.</param>
|
||||||
|
/// <param name="format">The format string that dictates the formatting of the date. If the format includes the "//" symbol,
|
||||||
|
/// it splits the string at "//" and divides the left-side value by the right-side value. The format string can include standard
|
||||||
|
/// <see cref="DateTime.ToString"/> format patterns.</param>
|
||||||
|
/// <returns>A string representation of the formatted date, or the result of the division operation if "//" is present in the format.</returns>
|
||||||
|
/// <exception cref="ArgumentException">Thrown if the format string is invalid, such as having an incorrect number of parts after "//".</exception>
|
||||||
|
/// <exception cref="DivideByZeroException">Thrown if the right side of the "//" contains a zero, resulting in division by zero.</exception>
|
||||||
|
/// <exception cref="FormatException">Thrown if either the left-side or right-side value of "//" cannot be parsed as an integer.</exception>
|
||||||
|
internal static string ToTag(this DateTime date, string format)
|
||||||
|
{
|
||||||
|
if (format is not null && format.Contains("//"))
|
||||||
|
{
|
||||||
|
var subStrings = format.Split("//");
|
||||||
|
|
||||||
|
if (subStrings.Length != 2)
|
||||||
|
throw new ArgumentException($"Date tag format {format} is invalid. It must contain exactly one '//' separator.", nameof(format));
|
||||||
|
|
||||||
|
var formattedLeft = date.ToString(subStrings[0]);
|
||||||
|
|
||||||
|
if (!int.TryParse(formattedLeft, out var dateValue))
|
||||||
|
throw new FormatException($"The left-side value ({formattedLeft}) of the format could not be parsed to an integer.");
|
||||||
|
|
||||||
|
if (!int.TryParse(subStrings[1], out var divisor))
|
||||||
|
throw new FormatException($"The right-side value ({divisor}) of the format could not be parsed to an integer.");
|
||||||
|
|
||||||
|
if (divisor == 0)
|
||||||
|
throw new DivideByZeroException($"Date tag format {format} includes division by zero, which is not allowed.");
|
||||||
|
|
||||||
|
var result = (dateValue - 1) / divisor + 1;
|
||||||
|
return result.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return date.ToString(format);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a <see cref="DateTime"/> to a formatted string based on the specified format string.
|
||||||
|
/// <br />
|
||||||
|
/// - If the format contains the symbol “//”, the method divides the numeric value obtained from the left side of the format
|
||||||
|
/// by one minus the numeric value obtained from the right side of the format string and adds one. For instance:
|
||||||
|
/// <br />
|
||||||
|
/// - If the date is 02.03.2024 and the format is "MM//2", it extracts the month (02), subtracts one (3), divides it by 2,
|
||||||
|
/// rounds down the outgoing number (1), adds one to the number (resulting in 2).
|
||||||
|
/// <br />
|
||||||
|
/// - If the format does not contain "//", the method uses the default <see cref="DateTime.ToString"/> format.
|
||||||
|
/// <br />
|
||||||
|
/// This method provides a way to format the date based on typical or customized rules, including mathematical operations like division.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="date">The <see cref="DateOnly"/> value to be formatted. It will convert to DateTime to use the method shared with DateTime.</param>
|
||||||
|
/// <param name="format">The format string that dictates the formatting of the date. If the format includes the "//" symbol,
|
||||||
|
/// it splits the string at "//" and divides the left-side value by the right-side value. The format string can include standard
|
||||||
|
/// <see cref="DateTime.ToString"/> format patterns.</param>
|
||||||
|
/// <returns>A string representation of the formatted date, or the result of the division operation if "//" is present in the format.</returns>
|
||||||
|
/// <exception cref="ArgumentException">Thrown if the format string is invalid, such as having an incorrect number of parts after "//".</exception>
|
||||||
|
/// <exception cref="DivideByZeroException">Thrown if the right side of the "//" contains a zero, resulting in division by zero.</exception>
|
||||||
|
/// <exception cref="FormatException">Thrown if either the left-side or right-side value of "//" cannot be parsed as an integer.</exception>
|
||||||
|
internal static string ToTag(this DateOnly date, string format) => date.ToDateTime(new()).ToTag(format);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maps a <see cref="RSATokenDescriptor"/> to a <see cref="SecurityTokenDescriptor"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mapper">The <see cref="IMapper"/> instance used for mapping.</param>
|
||||||
|
/// <param name="description">The <see cref="RSATokenDescriptor"/> instance to be mapped.</param>
|
||||||
|
/// <returns>A <see cref="SecurityTokenDescriptor"/> instance populated with the mapped values.</returns>
|
||||||
|
/// <exception cref="ArgumentNullException">Thrown if <paramref name="mapper"/> or <paramref name="description"/> is <c>null</c>.</exception>
|
||||||
|
internal static SecurityTokenDescriptor Map(this IMapper mapper, IAsymmetricTokenDescriptor description)
|
||||||
|
=> mapper.Map(description, new SecurityTokenDescriptor());
|
||||||
|
}
|
||||||
|
}
|
||||||
8
DigitalData.Core.Security/GlobalSuppressions.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
// This file is used by Code Analysis to maintain SuppressMessage
|
||||||
|
// attributes that are applied to this project.
|
||||||
|
// Project-level suppressions either have no target or are given
|
||||||
|
// a specific target and scoped to a namespace, type, member, etc.
|
||||||
|
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
[assembly: SuppressMessage("Style", "IDE0290:Use primary constructor", Justification = "<Pending>", Scope = "member", Target = "~M:DigitalData.Core.Security.JwtSignatureHandler`1.#ctor(Microsoft.Extensions.Options.IOptions{DigitalData.Core.Security.Config.ClaimDescriptor{`0}},AutoMapper.IMapper)")]
|
||||||
14
DigitalData.Core.Security/Instance.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using DigitalData.Core.Abstractions.Security;
|
||||||
|
using DigitalData.Core.Security.Config;
|
||||||
|
using DigitalData.Core.Security.RSAKey;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
namespace DigitalData.Core.Security
|
||||||
|
{
|
||||||
|
public static class Instance
|
||||||
|
{
|
||||||
|
private static readonly Lazy<RSAFactory<RSAFactoryParams>> LazyInstance = new(() => new(Options.Create<RSAFactoryParams>(new())));
|
||||||
|
|
||||||
|
public static IAsymmetricKeyFactory RSAFactory => LazyInstance.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
40
DigitalData.Core.Security/JwtSignatureHandler.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
using AutoMapper;
|
||||||
|
using DigitalData.Core.Abstractions.Security;
|
||||||
|
using DigitalData.Core.Security.Config;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
|
||||||
|
namespace DigitalData.Core.Security
|
||||||
|
{
|
||||||
|
public class JwtSignatureHandler<TPrincipal> : JwtSecurityTokenHandler, IJwtSignatureHandler<TPrincipal>
|
||||||
|
{
|
||||||
|
private readonly ClaimDescriptor<TPrincipal> _claimDescriptor;
|
||||||
|
|
||||||
|
private readonly IMapper _mapper;
|
||||||
|
|
||||||
|
private readonly ICryptoFactory _cryptoFactory;
|
||||||
|
|
||||||
|
public JwtSignatureHandler(IOptions<ClaimDescriptor<TPrincipal>> claimDescriptorOptions, IMapper mapper, ICryptoFactory cryptoFactory)
|
||||||
|
{
|
||||||
|
_claimDescriptor = claimDescriptorOptions.Value;
|
||||||
|
_mapper = mapper;
|
||||||
|
_cryptoFactory = cryptoFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SecurityToken CreateToken(TPrincipal subject, IAsymmetricTokenDescriptor descriptor)
|
||||||
|
{
|
||||||
|
var sDescriptor = _mapper.Map(descriptor);
|
||||||
|
sDescriptor.Claims = _claimDescriptor.CreateClaims?.Invoke(subject);
|
||||||
|
sDescriptor.Subject = _claimDescriptor.CreateSubject?.Invoke(subject);
|
||||||
|
return CreateToken(sDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SecurityToken CreateToken(TPrincipal subject, string issuer, string audience)
|
||||||
|
{
|
||||||
|
var descriptor = _cryptoFactory.TokenDescriptors.Get(issuer: issuer, audience: audience)
|
||||||
|
?? throw new InvalidOperationException($"No or multiple token description found for issuer '{issuer}' and audience '{audience}'.");
|
||||||
|
return CreateToken(subject: subject, descriptor: descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
33
DigitalData.Core.Security/RSAKey/RSADecryptor.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
using DigitalData.Core.Abstractions.Security;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace DigitalData.Core.Security.RSAKey
|
||||||
|
{
|
||||||
|
public class RSADecryptor : RSAPrivateKey, IAsymmetricDecryptor
|
||||||
|
{
|
||||||
|
public RSAEncryptionPadding Padding { get; init; } = RSAEncryptionPadding.OaepSHA256;
|
||||||
|
|
||||||
|
// TODO: add as json converter to IConfigurIConfiguration.Config
|
||||||
|
public string PaddingName
|
||||||
|
{
|
||||||
|
get => Padding.ToString();
|
||||||
|
init => Padding = typeof(RSAEncryptionPadding).GetProperty(value, BindingFlags.Public | BindingFlags.Static)?.GetValue(null) as RSAEncryptionPadding ?? throw new ArgumentException($"Padding '{value}' not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Decrypt(byte[] data) => RSA.Decrypt(data, Padding);
|
||||||
|
|
||||||
|
private readonly Lazy<IAsymmetricEncryptor> _lazyEncryptor;
|
||||||
|
|
||||||
|
public IAsymmetricEncryptor Encryptor => _lazyEncryptor.Value;
|
||||||
|
|
||||||
|
public RSADecryptor()
|
||||||
|
{
|
||||||
|
_lazyEncryptor = new(() => new RSAEncryptor()
|
||||||
|
{
|
||||||
|
Content = RSA.ExportRSAPublicKeyPem(),
|
||||||
|
Padding = Padding
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
DigitalData.Core.Security/RSAKey/RSAEncryptor.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using DigitalData.Core.Abstractions.Security;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace DigitalData.Core.Security.RSAKey
|
||||||
|
{
|
||||||
|
public class RSAEncryptor : RSAPublicKey, IAsymmetricEncryptor
|
||||||
|
{
|
||||||
|
public RSAEncryptionPadding Padding { get; init; } = RSAEncryptionPadding.OaepSHA256;
|
||||||
|
|
||||||
|
// TODO: add as json converter to IConfigurIConfiguration.Config
|
||||||
|
public string PaddingName
|
||||||
|
{
|
||||||
|
get => Padding.ToString();
|
||||||
|
init => Padding = typeof(RSAEncryptionPadding).GetProperty(value, BindingFlags.Public | BindingFlags.Static)?.GetValue(null) as RSAEncryptionPadding ?? throw new ArgumentException($"Padding '{value}' not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Encrypt(byte[] data) => RSA.Encrypt(data, Padding);
|
||||||
|
}
|
||||||
|
}
|
||||||
66
DigitalData.Core.Security/RSAKey/RSAFactory.cs
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
using DigitalData.Core.Abstractions.Security;
|
||||||
|
using DigitalData.Core.Security.Config;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace DigitalData.Core.Security.RSAKey
|
||||||
|
{
|
||||||
|
public class RSAFactory<TRSAFactoryParams> : IAsymmetricKeyFactory where TRSAFactoryParams : RSAFactoryParams
|
||||||
|
{
|
||||||
|
protected readonly TRSAFactoryParams _params;
|
||||||
|
|
||||||
|
public RSAFactory(IOptions<TRSAFactoryParams> options)
|
||||||
|
{
|
||||||
|
options.Value.Init();
|
||||||
|
_params = options.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string CreatePrivateKeyPem(int? keySizeInBits = null, bool encrypt = false) => encrypt
|
||||||
|
? CreateEncryptedPrivateKeyPem(keySizeInBits: keySizeInBits)
|
||||||
|
: RSA.Create(keySizeInBits ?? _params.KeySizeInBits).ExportRSAPrivateKeyPem();
|
||||||
|
|
||||||
|
public string CreateEncryptedPrivateKeyPem(
|
||||||
|
PbeEncryptionAlgorithm? pbeEncryptionAlgorithm = null,
|
||||||
|
HashAlgorithmName? hashAlgorithmName = null,
|
||||||
|
int? iterationCount = null,
|
||||||
|
int? keySizeInBits = null,
|
||||||
|
string? password = null)
|
||||||
|
{
|
||||||
|
password ??= _params.PbePassword;
|
||||||
|
|
||||||
|
var pbeParameters = pbeEncryptionAlgorithm is null && hashAlgorithmName is null && iterationCount is null
|
||||||
|
? new PbeParameters(
|
||||||
|
pbeEncryptionAlgorithm ?? _params.PbeEncryptionAlgorithm,
|
||||||
|
hashAlgorithmName ?? _params.PbeHashAlgorithm,
|
||||||
|
iterationCount ?? _params.PbeIterationCount)
|
||||||
|
: _params.PbeParameters;
|
||||||
|
|
||||||
|
var encryptedPrivateKey = RSA.Create(keySizeInBits ?? _params.KeySizeInBits).ExportEncryptedPkcs8PrivateKey(password.AsSpan(), pbeParameters);
|
||||||
|
|
||||||
|
var pemChars = PemEncoding.Write(_params.EncryptedPrivateKeyPemLabel, encryptedPrivateKey);
|
||||||
|
|
||||||
|
return new string(pemChars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string CreateEncryptedPrivateKeyPem(
|
||||||
|
PbeParameters pbeParameters,
|
||||||
|
int? keySizeInBits = null,
|
||||||
|
string? password = null)
|
||||||
|
{
|
||||||
|
password ??= _params.PbePassword;
|
||||||
|
|
||||||
|
var encryptedPrivateKey = RSA.Create(keySizeInBits ?? _params.KeySizeInBits).ExportEncryptedPkcs8PrivateKey(password.AsSpan(), pbeParameters);
|
||||||
|
|
||||||
|
var pemChars = PemEncoding.Write(_params.EncryptedPrivateKeyPemLabel, encryptedPrivateKey);
|
||||||
|
|
||||||
|
return new string(pemChars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IAsymmetricDecryptor CreateDecryptor(string pem, string? issuer = null, string? audience = null, bool encrypt = false, RSAEncryptionPadding? padding = null) => new RSADecryptor()
|
||||||
|
{
|
||||||
|
Content = pem,
|
||||||
|
IsEncrypted = encrypt,
|
||||||
|
Padding = padding ?? RSAEncryptionPadding.OaepSHA256
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
16
DigitalData.Core.Security/RSAKey/RSAKeyBase.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using DigitalData.Core.Abstractions.Security;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace DigitalData.Core.Security.RSAKey
|
||||||
|
{
|
||||||
|
public class RSAKeyBase : IAsymmetricKey
|
||||||
|
{
|
||||||
|
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||||
|
public virtual string Content { get; init; }
|
||||||
|
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||||
|
|
||||||
|
public string? Id { get; init; }
|
||||||
|
|
||||||
|
protected virtual RSA RSA { get; } = RSA.Create();
|
||||||
|
}
|
||||||
|
}
|
||||||
55
DigitalData.Core.Security/RSAKey/RSAPrivateKey.cs
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
using DigitalData.Core.Abstractions.Security;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace DigitalData.Core.Security.RSAKey
|
||||||
|
{
|
||||||
|
public class RSAPrivateKey : RSAKeyBase, IAsymmetricPrivateKey, IAsymmetricKey
|
||||||
|
{
|
||||||
|
private string? _pem;
|
||||||
|
|
||||||
|
public override string Content
|
||||||
|
{
|
||||||
|
#pragma warning disable CS8603 // Possible null reference return.
|
||||||
|
get => _pem;
|
||||||
|
#pragma warning restore CS8603 // Possible null reference return.
|
||||||
|
init
|
||||||
|
{
|
||||||
|
_pem = value;
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsPemNull => _pem is null;
|
||||||
|
|
||||||
|
public bool IsEncrypted { get; init; }
|
||||||
|
|
||||||
|
protected TPublicKey CreatePublicKey<TPublicKey>() where TPublicKey : RSAPublicKey, new()
|
||||||
|
=> new() { Content = RSA.ExportRSAPublicKeyPem() };
|
||||||
|
|
||||||
|
private readonly Lazy<RSAPublicKey> _lazyPublicKey;
|
||||||
|
|
||||||
|
public IAsymmetricPublicKey PublicKey => _lazyPublicKey.Value;
|
||||||
|
|
||||||
|
public RSAPrivateKey()
|
||||||
|
{
|
||||||
|
_lazyPublicKey = new(CreatePublicKey<RSAPublicKey>);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void SetPem(string pem)
|
||||||
|
{
|
||||||
|
_pem = pem;
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Init()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(_pem))
|
||||||
|
throw new InvalidOperationException ($"The content of RSA private key is null or empty. Id: {Id}.");
|
||||||
|
|
||||||
|
if (IsEncrypted)
|
||||||
|
RSA.ImportFromEncryptedPem(Content, Secrets.PBE_PASSWORD.AsSpan());
|
||||||
|
else
|
||||||
|
RSA.ImportFromPem(Content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
DigitalData.Core.Security/RSAKey/RSAPublicKey.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using DigitalData.Core.Abstractions.Security;
|
||||||
|
|
||||||
|
namespace DigitalData.Core.Security.RSAKey
|
||||||
|
{
|
||||||
|
public class RSAPublicKey : RSAKeyBase, IAsymmetricPublicKey, IAsymmetricKey
|
||||||
|
{
|
||||||
|
public override string Content
|
||||||
|
{
|
||||||
|
get => base.Content;
|
||||||
|
init
|
||||||
|
{
|
||||||
|
base.Content = value;
|
||||||
|
RSA.ImportFromPem(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
119
DigitalData.Core.Security/RSAKey/RSATokenDescriptor.cs
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
using DigitalData.Core.Abstractions.Security;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
|
||||||
|
namespace DigitalData.Core.Security.RSAKey
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Contains some information which used to create a security token. Designed to abstract <see cref="SecurityTokenDescriptor"/>
|
||||||
|
/// </summary>
|
||||||
|
public class RSATokenDescriptor : RSAPrivateKey, IAsymmetricTokenDescriptor
|
||||||
|
{
|
||||||
|
private readonly Lazy<RSATokenValidator> _lazyTokenValidator;
|
||||||
|
|
||||||
|
public IAsymmetricTokenValidator Validator => _lazyTokenValidator.Value;
|
||||||
|
|
||||||
|
public required TimeSpan Lifetime { get; init; }
|
||||||
|
|
||||||
|
#region SecurityTokenDescriptor Map
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the value of the 'audience' claim.
|
||||||
|
/// </summary>
|
||||||
|
public required string Audience { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the compression algorithm that will be used to compress the JWT token payload.
|
||||||
|
/// </summary>
|
||||||
|
public string CompressionAlgorithm { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the <see cref="EncryptingCredentials"/> used to create a encrypted security token.
|
||||||
|
/// </summary>
|
||||||
|
public EncryptingCredentials EncryptingCredentials { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the value of the 'expiration' claim. This value should be in UTC.
|
||||||
|
/// The expiration time is the sum of DateTime.Now and LifeTime.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime? Expires => DateTime.Now.AddTicks(Lifetime.Ticks);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the issuer of this <see cref="SecurityTokenDescriptor"/>.
|
||||||
|
/// </summary>
|
||||||
|
public required string Issuer { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the time the security token was issued. This value should be in UTC.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime? IssuedAt { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the notbefore time for the security token. This value should be in UTC.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime? NotBefore { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the token type.
|
||||||
|
/// <remarks> If provided, this will be added as the value for the 'typ' header parameter. In the case of a JWE, this will be added to both the inner (JWS) and the outer token (JWE) header. By default, the value used is 'JWT'.
|
||||||
|
/// If <see cref="AdditionalHeaderClaims"/> also contains 'typ' header claim value, it will override the TokenType provided here.
|
||||||
|
/// This value is used only for JWT tokens and not for SAML/SAML2 tokens</remarks>
|
||||||
|
/// </summary>
|
||||||
|
public string TokenType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the <see cref="Dictionary{TKey, TValue}"/> which contains any custom header claims that need to be added to the JWT token header.
|
||||||
|
/// The 'alg', 'kid', 'x5t', 'enc', and 'zip' claims are added by default based on the <see cref="SigningCredentials"/>,
|
||||||
|
/// <see cref="EncryptingCredentials"/>, and/or <see cref="CompressionAlgorithm"/> provided and SHOULD NOT be included in this dictionary as this
|
||||||
|
/// will result in an exception being thrown.
|
||||||
|
/// <remarks> These claims are only added to the outer header (in case of a JWE).</remarks>
|
||||||
|
/// </summary>
|
||||||
|
public IDictionary<string, object> AdditionalHeaderClaims { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the <see cref="Dictionary{TKey, TValue}"/> which contains any custom header claims that need to be added to the inner JWT token header.
|
||||||
|
/// The 'alg', 'kid', 'x5t', 'enc', and 'zip' claims are added by default based on the <see cref="SigningCredentials"/>,
|
||||||
|
/// <see cref="EncryptingCredentials"/>, and/or <see cref="CompressionAlgorithm"/> provided and SHOULD NOT be included in this dictionary as this
|
||||||
|
/// will result in an exception being thrown.
|
||||||
|
/// <remarks>
|
||||||
|
/// For JsonWebTokenHandler, these claims are merged with <see cref="AdditionalHeaderClaims"/> while adding to the inner JWT header.
|
||||||
|
/// </remarks>
|
||||||
|
/// </summary>
|
||||||
|
public IDictionary<string, object> AdditionalInnerHeaderClaims { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the <see cref="SigningCredentials"/> used to create a security token.
|
||||||
|
/// </summary>
|
||||||
|
public SigningCredentials SigningCredentials => _lazySigningCredentials.Value;
|
||||||
|
#endregion SecurityTokenDescriptor
|
||||||
|
|
||||||
|
private readonly Lazy<RsaSecurityKey> _lazyRsaSecurityKey;
|
||||||
|
|
||||||
|
public SecurityKey SecurityKey => _lazyRsaSecurityKey.Value;
|
||||||
|
|
||||||
|
private readonly Lazy<SigningCredentials> _lazySigningCredentials;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies the signature algorithm to be applied to the <see cref="SigningCredentials"/>.
|
||||||
|
/// Default is <see cref="SecurityAlgorithms.RsaSha256"/>.
|
||||||
|
/// </summary>
|
||||||
|
public string SigningAlgorithm { get; init; } = SecurityAlgorithms.RsaSha256;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optionally specifies the digest algorithm to be applied during the signing process for the <see cref="SigningCredentials"/>.
|
||||||
|
/// If not provided, the default algorithm is used.
|
||||||
|
/// </summary>
|
||||||
|
public string? SigningDigest { get; init; }
|
||||||
|
|
||||||
|
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||||
|
public RSATokenDescriptor()
|
||||||
|
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||||
|
{
|
||||||
|
_lazyTokenValidator = new(CreatePublicKey<RSATokenValidator>);
|
||||||
|
|
||||||
|
_lazyRsaSecurityKey = new(() => new RsaSecurityKey(RSA));
|
||||||
|
|
||||||
|
_lazySigningCredentials = new(() => SigningDigest is null
|
||||||
|
? new(SecurityKey, SigningAlgorithm)
|
||||||
|
: new(SecurityKey, SigningAlgorithm, SigningDigest));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
DigitalData.Core.Security/RSAKey/RSATokenValidator.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using DigitalData.Core.Abstractions.Security;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
|
||||||
|
namespace DigitalData.Core.Security.RSAKey
|
||||||
|
{
|
||||||
|
public class RSATokenValidator : RSAPublicKey, IAsymmetricTokenValidator
|
||||||
|
{
|
||||||
|
private readonly Lazy<RsaSecurityKey> _lazyRsaSecurityKey;
|
||||||
|
|
||||||
|
public SecurityKey SecurityKey => _lazyRsaSecurityKey.Value;
|
||||||
|
|
||||||
|
public RSATokenValidator()
|
||||||
|
{
|
||||||
|
_lazyRsaSecurityKey = new(() => new RsaSecurityKey(RSA));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
DigitalData.Core.Security/Secrets.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace DigitalData.Core.Security
|
||||||
|
{
|
||||||
|
public static class Secrets
|
||||||
|
{
|
||||||
|
public static readonly DateTime CreationDate = new (2024, 11, 19);
|
||||||
|
|
||||||
|
public static readonly Version Version = new (1, 0);
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
internal static readonly string PBE_PASSWORD = "9mk@i/$QY&Mw@_--dI^ahlXpNKEtv_U-,V-46b19_-Z6-U_*89_n1_-5-r-_+_$_IY_mYQl-";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
using DigitalData.Core.Client;
|
using DigitalData.Core.Client;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace DigitalData.Core.Tests
|
namespace DigitalData.Core.Tests.Client
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class BaseHttpClientServiceTests
|
public class BaseHttpClientServiceTests
|
||||||
@@ -14,22 +14,46 @@ namespace DigitalData.Core.Tests
|
|||||||
public void SetUp()
|
public void SetUp()
|
||||||
{
|
{
|
||||||
_serviceProvider = new ServiceCollection()
|
_serviceProvider = new ServiceCollection()
|
||||||
.AddHttpClientService("https://jsonplaceholder.typicode.com/todos")
|
.AddHttpClientService("https://jsonplaceholder.typicode.com", "todos")
|
||||||
.BuildServiceProvider();
|
.BuildServiceProvider();
|
||||||
|
|
||||||
_service = _serviceProvider.GetRequiredService<IBaseHttpClientService>();
|
_service = _serviceProvider.GetRequiredService<IBaseHttpClientService>();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task FetchJsonAsync_ShouldReturnJsonResponse()
|
public async Task FetchJsonAsync_ShouldReturnJsonResponse_WithCorrectWithPath()
|
||||||
{
|
{
|
||||||
// Act
|
// Act
|
||||||
var expectedUserId = (int) await _service.FetchAsync("/1", sendWithCookie: false, saveCookie: false)
|
var expectedUserId = (int) await _service.FetchAsync(path: "/1", sendWithCookie: false, saveCookie: false)
|
||||||
.ThenAsync(res => res.Json())
|
.ThenAsync(res => res.Json())
|
||||||
.ThenAsync(todo => todo.userId);
|
.ThenAsync(todo => todo.userId);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.That(expectedUserId, Is.EqualTo(1), "The userId of the fetched JSON object should be 1.");
|
Assert.That(expectedUserId, Is.EqualTo(1), "The userId of the fetched JSON object should be 1.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task FetchJsonAsync_ShouldReturnJsonResponse_WithQueryParams()
|
||||||
|
{
|
||||||
|
var queryParams = new Dictionary<string, object?>
|
||||||
|
{
|
||||||
|
{ "id", "1" }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var dyn_id = await _service.FetchAsync(queryParams: queryParams, sendWithCookie: false, saveCookie: false)
|
||||||
|
.ThenAsync(res => res.JsonList())
|
||||||
|
.ThenAsync(todo => todo.FirstOrDefault()?.userId);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Assert.That((int)dyn_id, Is.EqualTo(1), "The userId of the fetched JSON object should be 1.");
|
||||||
|
}
|
||||||
|
catch (InvalidCastException)
|
||||||
|
{
|
||||||
|
// Handle the case where the cast is not possible
|
||||||
|
Assert.Fail("The id could not be cast to an integer.");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
@@ -26,6 +26,7 @@
|
|||||||
<ProjectReference Include="..\DigitalData.Core.Client\DigitalData.Core.Client.csproj" />
|
<ProjectReference Include="..\DigitalData.Core.Client\DigitalData.Core.Client.csproj" />
|
||||||
<ProjectReference Include="..\DigitalData.Core.DTO\DigitalData.Core.DTO.csproj" />
|
<ProjectReference Include="..\DigitalData.Core.DTO\DigitalData.Core.DTO.csproj" />
|
||||||
<ProjectReference Include="..\DigitalData.Core.Infrastructure\DigitalData.Core.Infrastructure.csproj" />
|
<ProjectReference Include="..\DigitalData.Core.Infrastructure\DigitalData.Core.Infrastructure.csproj" />
|
||||||
|
<ProjectReference Include="..\DigitalData.Core.Security\DigitalData.Core.Security.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||