90 Commits

Author SHA1 Message Date
Developer 02
65c64a3f9a chore(API): Aktualisiert auf 2.0.1 2024-12-02 11:35:33 +01:00
Developer 02
1d600aa453 refactor: Nullbarkeitsannotation zu ControllerExtensions-Methoden hinzugefügt 2024-12-02 11:33:52 +01:00
Developer 02
816d5835f1 fix(BaseHttpClientService): Die Kodierung der Abfrageparameter wurde entfernt, da UriBuilder dies bereits tut.
- Hochgestuft auf 2.0.3
2024-11-26 23:45:06 +01:00
Developer 02
4a64a31d47 refactor(Abstraction): Hochgestuft auf 2.2.1. 2024-11-25 14:30:20 +01:00
Developer 02
e9b2ba788f refactor(IHttpClientOptions): Konvertiert Typ der Header von Key Value Pair Liste zu Dictionary. 2024-11-25 14:29:21 +01:00
Developer 02
e53813500a chore(Core.Client): aufgerüstet auf 2.0.1 2024-11-25 14:05:17 +01:00
Developer 02
25e3855de2 refactor(DIExtensions): BaseHttpClientService-Injektion entfernen 2024-11-25 14:02:54 +01:00
Developer 02
dd3d6e70cc chore(Client): hochgestuft auf 2.2.0 2024-11-25 11:49:41 +01:00
Developer 02
02a87309df chore(Abstraktionen): hochgestuft auf 2.2.0 2024-11-25 11:47:45 +01:00
Developer 02
0f7bdc9d0e refactor: Vereinfachung der Logik zur Zusammenführung von Headern und Abfrageparametern in BaseHttpClientService
- Verbesserung der Zusammenführung von Standard-Headern und Abfrageparametern durch Null-Prüfung und übersichtlichere Handhabung.
- Sicherstellung, dass die Logik einfacher zu verstehen und zu warten ist.
2024-11-25 11:46:08 +01:00
Developer 02
f9df2fb29e feat: DI-Erweiterung für HttpClient-Services verbessert
- `AddHttpClientService` refaktoriert, um `AddHttpClientServiceDefaults` für gemeinsame Setup-Logik einzuführen.
- Überladungen für `AddHttpClientService` hinzugefügt, um sowohl `IConfigurationSection` als auch direkte Options-Instanz zu unterstützen.
- Bessere Erweiterbarkeit und sauberere Service-Konfiguration sichergestellt.
2024-11-25 11:35:46 +01:00
Developer 02
ef7da0e52c refactor(HttpClientOptions): entfernt und durch IHttpClientOptions mit Klasseneinschränkung ersetzt 2024-11-25 11:19:41 +01:00
Developer 02
f602a842be revert: IHttpClientOptions entfernen 2024-11-25 11:03:15 +01:00
Developer 02
52a7664e57 fix(Client.DIExtensions): Generischer Typ zur Injektion mehrerer Client-Dienste hinzugefügt 2024-11-25 10:58:45 +01:00
Developer 02
ea3d1312b8 refactor(BaseHttpClientService): aktualisiert, um den Pfad zu initialisieren emty string, wenn es null ist und HttpClientOptions ohne IOptions hinzugefügt 2024-11-25 10:54:34 +01:00
Developer 02
3b8b315fea refactor(IHttpClientOptions): removed 2024-11-25 10:42:22 +01:00
Developer 02
c65eefb954 feat(IHttpClientOptions): Abfrage-Parameter und Header hinzugefügt.
- Geordnete DI-Erweiterungen.
2024-11-25 10:30:33 +01:00
Developer 02
997fd533ac feat(BaseHttpClientService): Path getter und intter entfernt und geschützte readonly _path Variable hinzugefügt. 2024-11-25 10:11:13 +01:00
Developer 02
bcfb5a8a70 feat(BaseHttpClientService): Uri Getter und Setter entfernt und geschützte readonly _uri Variable hinzugefügt. 2024-11-25 10:09:05 +01:00
Developer 02
049e9977f4 feat(BaseHttpClientService): Optionale Standard-Header und QueryParams hinzugefügt 2024-11-25 10:05:42 +01:00
Developer 02
0334fc4cdf refactor(BaseHttpClientService): Verwendung von IEnumerable<KeyValuePair<string, object>> anstelle von Dictionary<string, string> in queryParams, form und headers inputs der FetchAsync Methode 2024-11-25 09:28:47 +01:00
Developer 02
0c2334cefb refactor(BaseHttpClientService): Der Wert von query params wurde zum nullbaren Objekt, um Flag-Parameter hinzuzufügen.
- Aktualisierte Schnittstelle und Logik unter Berücksichtigung dieser Situation
2024-11-22 14:35:22 +01:00
Developer 02
dd7f1c1ea0 fix(BaseHttpClientService): Null-Kontrolle zum Pfad hinzugefügt 2024-11-22 13:19:42 +01:00
Developer 02
4bb242a4cc feat(Tests.Client.BaseHttpClientServiceTests): Test für Abfrageparameter hinzugefügt 2024-11-22 12:48:36 +01:00
Developer 02
b577067379 chore: gitignore aktualisieren 2024-11-22 12:47:24 +01:00
Developer 02
bd4d4856ea feat(IHttpClientOptions):
Basispfad zu http-Client-Optionen hinzugefügt
2024-11-22 12:05:13 +01:00
Developer 02
c3a12ba5b7 chore: hochgestuft auf 1.1.0 2024-11-22 10:30:26 +01:00
Developer 02
478bf13a4a Revert "chore(Client): hochgestuft auf 2,1"
This reverts commit d8849f48da.
2024-11-22 10:29:03 +01:00
Developer 02
d8849f48da chore(Client): hochgestuft auf 2,1 2024-11-22 10:26:49 +01:00
Developer 02
c466c553dc chore: hochgestuft auf 2.1 2024-11-22 10:25:32 +01:00
Developer 02
48afa6b433 feat(BaseHttpClientService.FetchAsync): Schema-, Port-, Pfad- und Query-Parameter-Optionen hinzugefügt 2024-11-22 10:12:40 +01:00
Developer 02
e44b2895c9 feat(IHttpClientOptions): erstellt zur Abstraktion 2024-11-22 09:18:19 +01:00
Developer 02
85e5fc4018 feat(BaseHttpClientService): Header hinzugefügt 2024-11-22 09:15:04 +01:00
Developer 02
70ccec9fef feat(RSAFactory.ReadRSADecryptorAsync): ReadRSADecryptorAsync-Methode hinzugefügt, um die pem-Datei zu lesen und den Decryptor asynchron zu erstellen 2024-11-22 09:06:58 +01:00
Developer 02
f7193594b1 fix(RSAFactory): Dateiname und seine Erweiterung aus der Methode DefaultRSAKeyNameFormatter entfernt 2024-11-20 17:14:12 +01:00
Developer 02
9c7319634a fix(RSAExtensions): Schlüssel in Dateinamen umbenennen 2024-11-20 17:11:44 +01:00
Developer 02
3becb208ec fix(RSAExtensions): Falsche Methoden zur Schlüsselbenennung entfernt 2024-11-20 17:10:57 +01:00
Developer 02
1b00f9afa2 feat(CryptFactory): Der Parameter seperator der Funktionseigenschaft CryptFactory.RSAKeyNameFormatter ist jetzt nullbar. 2024-11-20 16:47:26 +01:00
Developer 02
b58d4aed2f feat(RSAFactory): Statische Readonly-Eigenschaft hinzugefügt, um den Standard-RSA-Schlüsselnamen-Separator zu speichern 2024-11-20 16:43:27 +01:00
Developer 02
5adc67edf2 feat (CryptFactory): Verschieben der Standardparameter des RSA-Namensformatierers in die RSAFactory 2024-11-20 16:40:24 +01:00
Developer 02
0ff0de8159 feat (CryptFactory.RSADecryptorKeyFormatter): aktualisiert, um die erforderlichen Parameter als Eingabe zu nehmen, anstatt IRSADecryptor direkt als Eingabe zu nehmen 2024-11-20 16:37:09 +01:00
Developer 02
49b49271f3 feat(CryptFactory): ValidateForbidden ve ValidateSeparator Methoden in DefaultRSADecryptorKeyFormatter hinzugefügt 2024-11-20 15:13:05 +01:00
Developer 02
5c5a6bd181 feat(CryptFactory): RSADecryptorKeyFormatter Funktionseigenschaft hinzugefügt, um standardisierte Schlüsselnamen zu erstellen 2024-11-20 14:18:55 +01:00
Developer 02
6ab1777f7c refactor(RSADecryptor): aktualisiert, um im Passwort- und Versions-Tupel-Format zu initieren, um Datenintegrität zu gewährleisten.
- password und PasswordVersion initter entfernt.
2024-11-20 12:49:36 +01:00
Developer 02
103ddf5c2e feat(RSADecryptor): PasswordVersion-Eigenschaft hinzugefügt. Password.get intern gemacht.
- Password.get entfernt und PasswordVersion-Eigenschaft in IRSADecryptor hinzugefügt
2024-11-20 11:17:38 +01:00
Developer 02
f9c94e8464 refactor(IRSADecryptor): HasEncryptedPem getter-Methode hinzugefügt 2024-11-20 10:52:39 +01:00
Developer 02
cdb0009e7c refactor(RSADecryptor): statt der Verwendung einer separaten init-Methode zur Initialisierung von RSA, wurde Lazy Loading verwendet. 2024-11-20 10:51:18 +01:00
Developer 02
5010224500 feat(RSADecryptor): Eigenschaft hinzugefügt, um zu prüfen, ob der RSADecryptor pem verschlüsselt hat. 2024-11-20 10:38:34 +01:00
Developer 02
1ebdd7e5bb feat(RSADecryptor): Öffentliche Constructure-Methode gemacht. 2024-11-20 10:33:11 +01:00
Developer 02
0e0513e640 feat(RSAExtensions): Methoden zum Speichern von IRSACryptographer.Pem erstellt. 2024-11-20 10:32:25 +01:00
Developer 02
683b95c205 refactor(RSAExtensions): GetRSADecryptor, TryGetRSADecryptor, GetRSAEncryptor und TryGetRSADecryptor Methoden hinzugefügt. 2024-11-20 00:15:27 +01:00
Developer 02
f28b43cc06 refactor(RSADecryptor): Lazy Loading in Encryptor Getter integriert, um die Leistung zu verbessern. 2024-11-19 23:58:04 +01:00
Developer 02
777a8a73ac refactor: AddSecurity-Methode aktualisiert, um ICryptFactory direkt mit der CryptFactory-Instanz zu registrieren 2024-11-19 23:51:49 +01:00
Developer 02
77fc06991b feat(CryptFactory): Erstellung einer separaten RSAFactory zur Erzeugung einer statischen Instanz 2024-11-19 23:49:34 +01:00
Developer 02
eeb50e837d feat: Unterstützung für IRSADecryptor und Verwaltung der RSA-Entschlüsselung in den Klassen ICryptFactory und CryptFactory hinzugefügt
ICryptFactory:
- `IRSADecryptor this[string key]`-Indexer für den Zugriff auf Entschlüssler per Schlüssel hinzugefügt.
- Methode `TryGetRSADecryptor` für das sichere Abrufen von Entschlüsslern eingeführt.

CryptFactory:
- `IRSADecryptor`-Indexer für die Verwaltung von Entschlüsslern implementiert.
- Ein `Decryptors`-Dictionary hinzugefügt, um RSA-Entschlüssler nach Schlüssel zu speichern.
- Konstruktor aktualisiert, um `Decryptors` mit einem bereitgestellten oder leeren Dictionary zu initialisieren.
- `TryGetRSADecryptor` zur Entschlüssler-Abfrage implementiert.
2024-11-19 23:14:44 +01:00
Developer 02
1b210714fd feat(CryptFactory): Startprotokoll hinzugefügt, um Informationen über Core.Secrets bereitzustellen 2024-11-19 20:01:54 +01:00
Developer 02
806bc01c17 refactor(PbePassword): CryptFactory.PbePassword.get privat und Secrets.PBE_PASSWORD intern gemacht.
- JsonIgnore-Attribut zu Secrets.PBE_PASSWORD hinzugefügt
 - ICryptFactory.PbePassword.get wurde entfernt.
2024-11-19 19:44:52 +01:00
Developer 02
0169097671 Chore: Hinzufügen des .net 8-Frameworks zu allen .net-Projekten.
- Zentralisierte Nuget-Symbole.
 - Entfernte Projekte gelöscht.
2024-11-19 19:21:40 +01:00
Developer 02
90c73237eb feat(Secrets): Statische Klasse Secrets erstellt, um feste Werte wie pbe password zu speichern.
- Statische Eigenschaften wie Version und Erstellungsdatum hinzugefügt, um versteckte Konstanten in der Produktion nach einem Produktionsupdate zu verfolgen.
2024-11-19 18:08:11 +01:00
Developer 02
2a9c9551b8 refactor(ICryptFactory.Password): umbenennen in PbePassword 2024-11-19 17:16:41 +01:00
Developer 02
a39728dff5 refactor(CryptFactory.Password): umbenennen in PbePassword 2024-11-19 17:14:54 +01:00
Developer 02
7048f385ef feat: Erweiterung der CryptFactory um RSA-Schlüsselerzeugung und Verschlüsselungsunterstützung
- Hinzugefügt: Eigenschaften KeySizeInBits, Password, PbeEncryptionAlgorithm, PbeHashAlgorithmName, PbeIterationCount und EncryptedPrivateKeyPemLabel zur Unterstützung der Konfiguration von RSA-Schlüsselerzeugung und Verschlüsselung in der CryptFactory.

 - Hinzugefügt: Methoden CreateRSAPrivateKeyPem und CreateEncryptedPrivateKeyPem zur Erstellung von RSA-Privatschlüsseln und verschlüsselten Private-Key-PEMs.

 - Geändert: ICryptFactory-Schnittstelle um neue Eigenschaften und Methoden erweitert.
2024-11-19 17:11:52 +01:00
Developer 02
cb9c5746b0 feat(CryptFactory.LazyStaticCryptFactory): umbenennen in LazyInstance 2024-11-19 13:47:31 +01:00
Developer 02
ed36015d1e fix: CryptFactory.Instance in Getter-Methode für träges Laden umwandeln 2024-11-19 13:32:38 +01:00
Developer 02
6ce4a08c53 feat: DI-Erweiterung zur Registrierung von CryptFactory hinzugefügt 2024-11-19 13:19:14 +01:00
Developer 02
4c379c2d4d feat(RSAExtensions) : Methoden hinzugefügt, um einen Verschlüsseler anhand seines Ausstellers und seiner Zielgruppe aus einem Wörterbuch zu erhalten 2024-11-18 17:56:21 +01:00
Developer 02
fee43c00ca feat(CryptFactory) : initiliazierte Schnittstellen.
- Lazy-Methode hinzugefügt, um statische CryptFactory zu beweisen
2024-11-18 17:44:55 +01:00
Developer 02
ee3060158e refactor(RSADecryptor): Konstruktionsmethode intern gemacht 2024-11-18 17:35:01 +01:00
Developer 02
4e615d7e39 feat(RSACryptographer): RSAEncryptionPadding nicht erforderlich gemacht und OaepSHA256 als Standard zugewiesen 2024-11-18 17:32:14 +01:00
Developer 02
d1fea581d7 feat(Tests.Security): initialisiert RSADecryptorTests. 2024-11-18 17:22:38 +01:00
Developer 02
26a68cd477 fix(Core.Security): pem-Importprozess in den Initilizer mehetods verschoben 2024-11-18 17:14:42 +01:00
Developer 02
eccf2b32ce Refactor(Core.Security): Getrennte Pem-Eigenschaften für öffentliche und private Schlüssel wurden entfernt.
- Pem-Eigenschaft in der Hauptklasse RSACryptographer erstellt
2024-11-18 14:39:18 +01:00
Developer 02
6ff0d0a876 feat(RSADecryptor): Aktualisiert für den Import von verschlüsseltem pem 2024-11-18 14:27:53 +01:00
Developer 02
0bb779b7b6 refactor(Core.Security): Implementierung der entsprechenden Schnittstellen zu RSACryptographer, RSADecryptor und RSAEncryptor. 2024-11-18 11:04:24 +01:00
Developer 02
51ebf3fa67 refactor(Core.Security): Entfernt die Erweiterungsmethoden im aktuellen Projekt.
- Projekt Security.Extensions hinzugefügt.
2024-11-18 10:58:34 +01:00
Developer 02
8cc6fd95f7 feat(Abstraktionen.Sicherheit): Schnittstellen für IRSACryptographer, IRSADecryptor und IRSAEncryptor erstellt. 2024-11-18 10:54:57 +01:00
Developer 02
c5b422921b feat(DigitalData.Core.Security.Extensions): Verschiebung der Methoden RSAExtensions und Extensions. 2024-11-18 10:42:48 +01:00
Developer 02
7b571e4d86 feat(DigitalData.Core.Security.Extensions): Initialisiert. 2024-11-18 10:41:16 +01:00
Developer 02
c39b554165 refactor(RSADecryptor): PublicKeyPem entfernt. 2024-11-18 10:36:15 +01:00
Developer 02
489ca67203 Refactor(RSACryptographer): Entfernte Pem initter Methode.
- PrivateKeyPem initter Methode zu RSADecryptor hinzugefügt.
 - PublicKeyPem getter und initter Methoden zu RSAEncryptor hinzugefügt.
2024-11-18 10:33:38 +01:00
Developer 02
0804ea1418 refactor: RSA-Kryptografie-Klassen für bessere Flexibilität und Effizienz überarbeitet
- Konstruktoren zu `RSACryptographer`, `RSADecryptor` und `RSAEncryptor` hinzugefügt, um die Initialisierung zu verbessern.
- `PublicKeyPem` in `RSADecryptor` optimiert, um unnötige Objekterstellungen zu vermeiden.
- `Verify`-Methode in `RSAEncryptor` korrigiert, um eine korrekte Signaturprüfung zu gewährleisten.
- Code-Wiederverwendbarkeit verbessert, indem Base64-Konvertierungslogik zentralisiert wurde.
2024-11-16 03:24:19 +01:00
Developer 02
84dbca97d5 feat(Core.Security): Erstellte Erweiterungsmethoden 2024-11-16 02:14:28 +01:00
Developer 02
8c350db146 chore: update gitignroe 2024-11-14 10:26:07 +01:00
Developer 02
471dace359 feat: Projekt initialisieren 2024-11-14 09:59:14 +01:00
Developer 02
a01e6e5b16 feat: Neue Erweiterungsmethoden zum Verarbeiten von Ergebnissen hinzufügen
- `HasAnyFlag` Methode hinzugefügt, um zu überprüfen, ob eine Benachrichtigung eines der angegebenen Flags hat.
- `Then` und `ThenAsync` Methoden für `Task<DataResult<T>>` Typ hinzugefügt, um asynchrone Ergebnisse basierend auf Erfolg oder Misserfolg zu verarbeiten.
2024-09-16 10:08:11 +02:00
Developer 02
96d03a5f59 chore: NuGet-Paketversionen für Application-, Infrastructure-, DTO- und Abstractions-Ebenen aktualisiert
- Version von 1.0.1.1 auf 2.0.0.0 für Application-, Infrastructure-, DTO- und Abstractions-Projekte aktualisiert.
2024-09-16 09:13:44 +02:00
Developer 02
993d407a48 feat: ReadService hinzugefügt und in ReadController integriert
- Generischen ReadService erstellt, um Lese- (ReadById, ReadAll) und Löschoperationen zu verwalten.
- ReadService in den ReadController integriert.
2024-09-16 09:08:27 +02:00
Developer 02
2c739fbf02 refactor: ICRUDService von IReadService erweitern und Methoden aktualisieren
- ICRUDService angepasst, um von IReadService zu erben, um die Wiederverwendbarkeit von Lesevorgängen zu fördern
- ICRUDService um `CreateAsync`- und `UpdateAsync`-Methoden mit geeigneten Rückgabetypen ergänzt
- Konsistenz gewährleistet durch Durchsetzung von IUnique<TId>-Einschränkungen für DTOs und Entitäten
2024-09-13 16:48:37 +02:00
Developer 02
dcd54266c0 refactor: IUnique<TId>-Einschränkungen in den Basis-Controller-Klassen durchsetzen
- Aktualisiert ReadControllerBase, um zu verlangen, dass TEntity IUnique<TId> implementiert
- BasicCRUDControllerBase geändert, um sicherzustellen, dass sowohl TDto als auch TEntity IUnique<TId> implementieren
2024-09-13 16:40:26 +02:00
Developer 02
0bf8979a09 refactor: Einführung des IUnique<TId>-Interfaces für Entitäten und DTOs
- Aktualisiertes IBasicCRUDService-Interface, um Konsistenz bei einzigartigen Identifikatoren mit IUnique<TId> durchzusetzen
- DIExtensions-Methoden angepasst, um IUnique<TId>-Einschränkungen für DTOs und Entitäten einzuschließen
2024-09-13 16:30:52 +02:00
92 changed files with 917 additions and 2533 deletions

2
.gitignore vendored
View File

@@ -408,3 +408,5 @@ FodyWeavers.xsd
/DigitalData.Core.ConsoleApp/DigitalData.Core.ConsoleApp.csproj
/DigitalData.Core.ConsoleApp/Program.cs
/DigitalData.Core.ConsoleApp/FooHttpOptions.cs
/DigitalData.Core.Tests/obj/
/DigitalData.Core.Terminal

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1020 KiB

View File

@@ -1,5 +1,5 @@
using DigitalData.Core.Abstractions;
using DigitalData.Core.Abstractions.Application;
using DigitalData.Core.Abstractions.Infrastructure;
using Microsoft.AspNetCore.Mvc;
namespace DigitalData.Core.API
@@ -8,8 +8,8 @@ namespace DigitalData.Core.API
[Route("api/[controller]")]
public class BasicCRUDControllerBase<TCRUDService, TDto, TEntity, TId> : CRUDControllerBase<TCRUDService, TDto, TDto, TDto, TEntity, TId>
where TCRUDService : ICRUDService<TDto, TDto, TDto, TEntity, TId>
where TDto : class
where TEntity : class
where TDto : class, IUnique<TId>
where TEntity : class, IUnique<TId>
{
public BasicCRUDControllerBase(ILogger logger, TCRUDService service) : base(logger, service)
{

View File

@@ -1,3 +1,4 @@
using DigitalData.Core.Abstractions;
using DigitalData.Core.Abstractions.Application;
using DigitalData.Core.DTO;
using Microsoft.AspNetCore.Mvc;
@@ -19,8 +20,8 @@ namespace DigitalData.Core.API
where TCRUDService : ICRUDService<TCreateDto, TReadDto, TUpdateDto, TEntity, TId>
where TCreateDto : class
where TReadDto : class
where TUpdateDto : class
where TEntity : class
where TUpdateDto : class, IUnique<TId>
where TEntity : class, IUnique<TId>
{
protected readonly ILogger _logger;
protected readonly TCRUDService _service;

View File

@@ -1,3 +1,4 @@
using DigitalData.Core.Abstractions;
using DigitalData.Core.Abstractions.Application;
using DigitalData.Core.DTO;
using Microsoft.AspNetCore.Mvc;
@@ -20,8 +21,8 @@ namespace DigitalData.Core.API
where TCRUDService : ICRUDService<TCreateDto, TReadDto, TUpdateDto, TEntity, TId>
where TCreateDto : class
where TReadDto : class
where TUpdateDto : class
where TEntity : class
where TUpdateDto : class, IUnique<TId>
where TEntity : class, IUnique<TId>
{
protected readonly ILogger _logger;
protected readonly TCRUDService _service;

View File

@@ -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="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>
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;
return viewResult;

View File

@@ -1,23 +1,32 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
<IsPackable>true</IsPackable>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<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>
<PackageId>DigitalData.Core.API</PackageId>
<Version>1.0.2.1</Version>
<Version>2.0.1</Version>
<Authors>Digital Data GmbH</Authors>
<Company>Digital Data GmbH</Company>
<Product>DigitalData.Core.API</Product>
<Copyright>Copyright 2024</Copyright>
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
<PackageTags>digital data core api</PackageTags>
<PackageIcon>Assets\icon.png</PackageIcon>
<PackageIcon>core_icon.png</PackageIcon>
<AssemblyVersion>2.0.1</AssemblyVersion>
<FileVersion>2.0.1</FileVersion>
</PropertyGroup>
<ItemGroup>
<None Include="..\..\nuget-package-icons\core_icon.png">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
</ItemGroup>

View File

@@ -12,13 +12,13 @@ namespace DigitalData.Core.API
/// <typeparam name="TId">The type of the entity's identifier.</typeparam>
[ApiController]
[Route("api/[controller]")]
public class ReadControllerBase<TBasicCRUDService, TReadDto, TEntity, TId> : ControllerBase
where TBasicCRUDService : IBasicCRUDService<TReadDto, TEntity, TId>
public class ReadControllerBase<TReadService, TReadDto, TEntity, TId> : ControllerBase
where TReadService : IReadService<TReadDto, TEntity, TId>
where TReadDto : class
where TEntity : class
{
protected readonly ILogger _logger;
protected readonly TBasicCRUDService _service;
protected readonly TReadService _service;
/// <summary>
/// Initializes a new instance of the CRUDControllerBase class with specified logger and CRUD service.
@@ -27,7 +27,7 @@ namespace DigitalData.Core.API
/// <param name="service">The CRUD service handling business logic for the entity.</param>
public ReadControllerBase(
ILogger logger,
TBasicCRUDService service)
TReadService service)
{
_logger = logger;
_service = service;

View File

@@ -13,13 +13,13 @@ namespace DigitalData.Core.API
/// <typeparam name="TId">The type of the entity's identifier.</typeparam>
[ApiController]
[Route("api/[controller]")]
public class ReadControllerBaseWithErrorHandling<TBasicCRUDService, TReadDto, TEntity, TId> : ControllerBase
where TBasicCRUDService : IBasicCRUDService<TReadDto, TEntity, TId>
public class ReadControllerBaseWithErrorHandling<TReadService, TReadDto, TEntity, TId> : ControllerBase
where TReadService : IReadService<TReadDto, TEntity, TId>
where TReadDto : class
where TEntity : class
{
protected readonly ILogger _logger;
protected readonly TBasicCRUDService _service;
protected readonly TReadService _service;
/// <summary>
/// Initializes a new instance of the CRUDControllerBase class with specified logger and CRUD service.
@@ -28,7 +28,7 @@ namespace DigitalData.Core.API
/// <param name="service">The CRUD service handling business logic for the entity.</param>
public ReadControllerBaseWithErrorHandling(
ILogger logger,
TBasicCRUDService service)
TReadService service)
{
_logger = logger;
_service = service;

View File

@@ -16,7 +16,7 @@ namespace DigitalData.Core.Abstractions.Application
/// allowing for a more concise and maintainable codebase when implementing services for such entities.
/// </remarks>
public interface IBasicCRUDService<TDto, TEntity, TId> : ICRUDService<TDto, TDto, TDto, TEntity, TId>
where TDto : class where TEntity : class
where TDto : class, IUnique<TId> where TEntity : class, IUnique<TId>
{
}
}

View File

@@ -1,27 +1,18 @@
using DigitalData.Core.Abstractions.Infrastructure;
using DigitalData.Core.DTO;
using DigitalData.Core.DTO;
namespace DigitalData.Core.Abstractions.Application
{
public interface ICRUDService<TCreateDto, TReadDto, TUpdateDto, TEntity, TId>
public interface ICRUDService<TCreateDto, TReadDto, TUpdateDto, TEntity, TId> : IReadService<TReadDto, TEntity, TId>
where TCreateDto : class where TReadDto : class where TUpdateDto : IUnique<TId> where TEntity : class, IUnique<TId>
{
/// <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}"/>.
/// The <see cref="DataResult{TId}"/> contains the identifier of the newly created entity on success or an error message on failure.
/// </summary>
/// <param name="createDto">The data transfer object containing the information for the new entity.</param>
/// <returns>A task representing the asynchronous operation, with a <see cref="DataResult{TId}"/> containing the identifier of the created entity or an error message.</returns>
Task<DataResult<TId>> CreateAsync(TCreateDto createDto);
/// <summary>
/// Retrieves an entity by its identifier and returns its readDTO representation wrapped in an IServiceResult,
/// including the readDTO on success or null and an error message on failure.
/// </summary>
/// <param name="id">The identifier of the entity to retrieve.</param>
/// <returns>An DataResult containing the readDTO representing the found entity or null, with an appropriate message.</returns>
Task<DataResult<TReadDto>> ReadByIdAsync(TId id);
/// <summary>
/// Retrieves all entities and returns their readDTO representations wrapped in an IServiceResult,
/// including a collection of readDTOs on success or an error message on failure.
/// </summary>
/// <returns>An DataResult containing a collection of readDTOs representing all entities or an error message.</returns>
Task<DataResult<IEnumerable<TReadDto>>> ReadAllAsync();
/// <summary>
/// Updates an existing entity based on the provided updateDTO and returns the result wrapped in an IServiceMessage,
@@ -30,20 +21,5 @@ namespace DigitalData.Core.Abstractions.Application
/// <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>
Task<Result> UpdateAsync(TUpdateDto updateDto);
/// <summary>
/// Deletes an entity by its identifier and returns the result wrapped in an IServiceMessage,
/// indicating the success or failure of the operation, including the error messages on failure.
/// </summary>
/// <param name="id">The identifier of the entity to delete.</param>
/// <returns>An Result indicating the outcome of the delete operation, with an appropriate message.</returns>
Task<Result> DeleteAsyncById(TId id);
/// <summary>
/// Asynchronously checks if an entity with the specified identifier exists within the data store.
/// </summary>
/// <param name="id">The identifier of the entity to check.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains a boolean value indicating whether the entity exists.</returns>
Task<bool> HasEntity(TId id);
}
}

View File

@@ -0,0 +1,38 @@
using DigitalData.Core.DTO;
namespace DigitalData.Core.Abstractions.Application
{
public interface IReadService<TReadDto, TEntity, TId>
where TReadDto : class where TEntity : class
{
/// <summary>
/// Retrieves an entity by its identifier and returns its readDTO representation wrapped in an IServiceResult,
/// including the readDTO on success or null and an error message on failure.
/// </summary>
/// <param name="id">The identifier of the entity to retrieve.</param>
/// <returns>An DataResult containing the readDTO representing the found entity or null, with an appropriate message.</returns>
Task<DataResult<TReadDto>> ReadByIdAsync(TId id);
/// <summary>
/// Retrieves all entities and returns their readDTO representations wrapped in an IServiceResult,
/// including a collection of readDTOs on success or an error message on failure.
/// </summary>
/// <returns>An DataResult containing a collection of readDTOs representing all entities or an error message.</returns>
Task<DataResult<IEnumerable<TReadDto>>> ReadAllAsync();
/// <summary>
/// Deletes an entity by its identifier and returns the result wrapped in an IServiceMessage,
/// indicating the success or failure of the operation, including the error messages on failure.
/// </summary>
/// <param name="id">The identifier of the entity to delete.</param>
/// <returns>An Result indicating the outcome of the delete operation, with an appropriate message.</returns>
Task<Result> DeleteAsyncById(TId id);
/// <summary>
/// Asynchronously checks if an entity with the specified identifier exists within the data store.
/// </summary>
/// <param name="id">The identifier of the entity to check.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains a boolean value indicating whether the entity exists.</returns>
Task<bool> HasEntity(TId id);
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1020 KiB

View File

@@ -4,15 +4,17 @@ namespace DigitalData.Core.Abstractions.Client
{
public interface IBaseHttpClientService
{
public string Uri { get; init; }
public CookieCollection GetCookies(string route = "");
CookieCollection GetCookies(string path = "");
Task<HttpResponseMessage> FetchAsync(
string route = "",
string? scheme = null,
int? port = null,
string path = "",
IEnumerable<KeyValuePair<string, object?>>? queryParams = null,
HttpMethod? method = 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 saveCookie = true
);

View 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; }
}
}

View File

@@ -1,6 +1,6 @@
namespace DigitalData.Core.Abstractions.Client
{
public interface IHttpClientService<TClientOptions> : IBaseHttpClientService
public interface IHttpClientService<TClientOptions> : IBaseHttpClientService where TClientOptions : IHttpClientOptions
{
}
}

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<!-- NuGet Package Metadata -->
@@ -16,11 +16,19 @@
<PackageProjectUrl></PackageProjectUrl>
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
<PackAsTool>False</PackAsTool>
<NeutralLanguage>aa-DJ</NeutralLanguage>
<PackageIcon>Assets\icon.png</PackageIcon>
<Version>1.0.1.1</Version>
<PackageIcon>core_icon.png</PackageIcon>
<Version>2.2.1</Version>
<AssemblyVersion>2.2.1</AssemblyVersion>
<FileVersion>2.2.1</FileVersion>
</PropertyGroup>
<ItemGroup>
<None Include="..\..\nuget-package-icons\core_icon.png">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.4" />
@@ -33,12 +41,4 @@
<ProjectReference Include="..\DigitalData.Core.DTO\DigitalData.Core.DTO.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="Assets\icon.png">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,48 @@
using System.Security.Cryptography;
namespace DigitalData.Core.Abstractions.Security
{
public interface ICryptFactory
{
int KeySizeInBits { get; init; }
string PbePassword { init; }
PbeEncryptionAlgorithm PbeEncryptionAlgorithm { get; init; }
HashAlgorithmName PbeHashAlgorithmName { get; init; }
int PbeIterationCount { get; init; }
PbeParameters PbeParameters { get; }
string EncryptedPrivateKeyPemLabel { get; init; }
/// <summary>
/// Gets the formatter function for generating RSA key names.
/// This formatter takes an issuer, audience, isPrivate, and optional version and separator
/// to produce a formatted string used for the key naming convention.
/// </summary>
/// <param name="issuer">A string representing the issuer of the key. It should not contain invalid file name characters or the separator.</param>
/// <param name="audience">A string representing the audience for which the key is intended. It should not contain invalid file name characters or the separator.</param>
/// <param name="isPrivate">An bool to check if the key is private.</param>
/// <param name="version">An instance of the <see cref="Version?"/> interface, which is used to keep the version of Pbe password.</param>
/// <param name="separator">An optional string separator used to separate the issuer and audience. The default is "-_-". It should not be included in the issuer or audience strings.</param>
/// <returns>A formatted string combining the issuer, audience, and separator, which adheres to valid file naming rules.</returns>
/// <exception cref="ArgumentException">Thrown when the issuer, audience, or separator contains invalid characters or when the separator is present within the issuer or audience.</exception>
Func<string, string, bool, Version?, string?, string> RSAKeyNameFormatter { get; }
string CreateRSAPrivateKeyPem(int? keySizeInBits = null);
string CreateEncryptedPrivateKeyPem(
int? keySizeInBits = null,
string? password = null,
PbeEncryptionAlgorithm? pbeEncryptionAlgorithm = null,
HashAlgorithmName? hashAlgorithmName = null,
int? iterationCount = null);
IRSADecryptor this[string key] { get; }
bool TryGetRSADecryptor(string key, out IRSADecryptor? decryptor);
}
}

View File

@@ -0,0 +1,11 @@
using System.Security.Cryptography;
namespace DigitalData.Core.Abstractions.Security
{
public interface IRSACryptographer
{
public string Pem { get; init; }
public RSAEncryptionPadding Padding { get; init; }
}
}

View File

@@ -0,0 +1,17 @@
namespace DigitalData.Core.Abstractions.Security
{
public interface IRSADecryptor : IRSACryptographer
{
(string Value, Version Version)? VersionedPassword { init; }
Version? PasswordVersion { get; }
bool HasEncryptedPem { get; }
IRSAEncryptor Encryptor { get; }
byte[] Decrypt(byte[] data);
string Decrypt(string data);
}
}

View File

@@ -0,0 +1,11 @@
namespace DigitalData.Core.Abstractions.Security
{
public interface IRSAEncryptor : IRSACryptographer
{
public byte[] Encrypt(byte[] data);
public string Encrypt(string data);
public bool Verify(string data, string signature) => Encrypt(data) == signature;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1020 KiB

View File

@@ -1,4 +1,5 @@
using AutoMapper;
using DigitalData.Core.Abstractions;
using DigitalData.Core.Abstractions.Application;
using DigitalData.Core.Abstractions.Infrastructure;
@@ -19,7 +20,7 @@ namespace DigitalData.Core.Application
/// </remarks>
public class BasicCRUDService<TCRUDRepository, TDto, TEntity, TId> :
CRUDService<TCRUDRepository, TDto, TDto, TDto, TEntity, TId>, IBasicCRUDService<TDto, TEntity, TId>
where TCRUDRepository : ICRUDRepository<TEntity, TId> where TDto : class where TEntity : class
where TCRUDRepository : ICRUDRepository<TEntity, TId> where TDto : class, IUnique<TId> where TEntity : class, IUnique<TId>
{
/// <summary>
/// Initializes a new instance of the BasicCRUDService with the specified repository, translation service, and AutoMapper configuration.

View File

@@ -15,21 +15,17 @@ namespace DigitalData.Core.Application
/// <typeparam name="TUpdateDto">The DTO type for update operations.</typeparam>
/// <typeparam name="TEntity">The entity type.</typeparam>
/// <typeparam name="TId">The type of the identifier for the entity.</typeparam>
public class CRUDService<TCRUDRepository, TCreateDto, TReadDto, TUpdateDto, TEntity, TId> : ICRUDService<TCreateDto, TReadDto, TUpdateDto, TEntity, TId>
public class CRUDService<TCRUDRepository, TCreateDto, TReadDto, TUpdateDto, TEntity, TId> : ReadService<TCRUDRepository, TReadDto, TEntity, TId>, ICRUDService<TCreateDto, TReadDto, TUpdateDto, TEntity, TId>
where TCRUDRepository : ICRUDRepository<TEntity, TId> where TCreateDto : class where TReadDto : class where TUpdateDto : IUnique<TId> where TEntity : class, IUnique<TId>
{
protected readonly TCRUDRepository _repository;
protected readonly IMapper _mapper;
/// <summary>
/// Initializes a new instance of the CRUDService class with the specified repository, translation service, and mapper.
/// </summary>
/// <param name="repository">The CRUD repository for accessing the database.</param>
/// <param name="mapper">The AutoMapper instance for mapping between DTOs and entity objects.</param>
public CRUDService(TCRUDRepository repository, IMapper mapper)
public CRUDService(TCRUDRepository repository, IMapper mapper) : base(repository: repository, mapper: mapper)
{
_repository = repository;
_mapper = mapper;
}
/// <summary>
@@ -44,30 +40,6 @@ namespace DigitalData.Core.Application
return createdEntity is null ? Result.Fail<TId>() : Result.Success(createdEntity.Id);
}
/// <summary>
/// Asynchronously reads an entity by its identifier and maps it to a read DTO.
/// </summary>
/// <param name="id">The identifier of the entity to read.</param>
/// <returns>A service result indicating success or failure, including the read DTO if successful.</returns>
public virtual async Task<DataResult<TReadDto>> ReadByIdAsync(TId id)
{
var entity = await _repository.ReadByIdAsync(id);
return entity is null
? Result.Fail<TReadDto>()
: Result.Success(_mapper.Map<TReadDto>(entity));
}
/// <summary>
/// Asynchronously reads all entities and maps them to read DTOs.
/// </summary>
/// <returns>A service result including a collection of read DTOs.</returns>
public virtual async Task<DataResult<IEnumerable<TReadDto>>> ReadAllAsync()
{
var entities = await _repository.ReadAllAsync();
var readDto = _mapper.Map<IEnumerable<TReadDto>>(entities);
return Result.Success(readDto);
}
/// <summary>
/// Asynchronously updates an entity based on the provided update DTO.
/// </summary>
@@ -86,28 +58,5 @@ namespace DigitalData.Core.Application
? Result.Success()
: Result.Fail();
}
/// <summary>
/// Asynchronously deletes an entity by its identifier.
/// </summary>
/// <param name="id">The identifier of the entity to delete.</param>
/// <returns>A service message indicating success or failure.</returns>
public virtual async Task<Result> DeleteAsyncById(TId id)
{
TEntity? entity = await _repository.ReadByIdAsync(id);
if (entity is null)
return Result.Fail();
bool isDeleted = await _repository.DeleteAsync(entity);
return isDeleted ? Result.Success() : Result.Fail();
}
/// <summary>
/// Asynchronously checks if an entity with the specified identifier exists.
/// </summary>
/// <param name="id">The identifier of the entity to check.</param>
/// <returns>A Task that represents the asynchronous operation. The task result contains a boolean value indicating whether the entity exists.</returns>
public virtual async Task<bool> HasEntity(TId id) => await _repository.CountAsync(id) > 0;
}
}

View File

@@ -1,4 +1,5 @@
using AutoMapper;
using DigitalData.Core.Abstractions;
using DigitalData.Core.Abstractions.Application;
using DigitalData.Core.Abstractions.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
@@ -23,7 +24,7 @@ namespace DigitalData.Core.Application
/// <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>
public static IServiceCollection AddCleanBasicCRUDService<TCRUDRepository, TDto, TEntity, TId, TProfile>(this IServiceCollection services, Action<IServiceCollection>? configureService = null)
where TCRUDRepository : ICRUDRepository<TEntity, TId> where TDto : class where TEntity : class where TProfile : Profile
where TCRUDRepository : ICRUDRepository<TEntity, TId> where TDto : class, IUnique<TId> where TEntity : class, IUnique<TId> where TProfile : Profile
{
services.AddScoped<IBasicCRUDService<TDto, TEntity, TId>, BasicCRUDService<TCRUDRepository, TDto, TEntity, TId>>();
configureService?.Invoke(services);
@@ -47,7 +48,7 @@ namespace DigitalData.Core.Application
/// <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>
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 where TEntity : class where TProfile : Profile
where TCRUDRepository : ICRUDRepository<TEntity, TId> where TCreateDto : class where TReadDto : class where TUpdateDto : 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>>();
configureService?.Invoke(services);

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
@@ -11,13 +11,14 @@
<Company>Digital Data GmbH</Company>
<Product>DigitalData.Core.Application</Product>
<Copyright>Copyright 2024</Copyright>
<PackageIcon>icon.png</PackageIcon>
<PackageIcon>core_icon.png</PackageIcon>
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
<PackageTags>digital data core application clean architecture</PackageTags>
<Version>2.0.0.0</Version>
</PropertyGroup>
<ItemGroup>
<None Include="..\DigitalData.Core.Abstractions\Assets\icon.png">
<None Include="..\..\nuget-package-icons\core_icon.png">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
@@ -38,11 +39,4 @@
<ProjectReference Include="..\DigitalData.Core.Abstractions\DigitalData.Core.Abstractions.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="Assets\icon.png">
<PackagePath>\</PackagePath>
<Pack>True</Pack>
</None>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,79 @@
using DigitalData.Core.Abstractions.Application;
using DigitalData.Core.Abstractions.Infrastructure;
using AutoMapper;
using DigitalData.Core.DTO;
using DigitalData.Core.Abstractions;
namespace DigitalData.Core.Application
{
/// <summary>
/// Provides generic Read (Read and Delete) operations for a specified type of entity.
/// </summary>
/// <typeparam name="TReadDto">The DTO type for read operations.</typeparam>
/// <typeparam name="TEntity">The entity type.</typeparam>
/// <typeparam name="TId">The type of the identifier for the entity.</typeparam>
public class ReadService<TCRUDRepository, TReadDto, TEntity, TId> : IReadService<TReadDto, TEntity, TId>
where TCRUDRepository : ICRUDRepository<TEntity, TId> where TReadDto : class where TEntity : class, IUnique<TId>
{
protected readonly TCRUDRepository _repository;
protected readonly IMapper _mapper;
/// <summary>
/// Initializes a new instance of the CRUDService class with the specified repository, translation service, and mapper.
/// </summary>
/// <param name="repository">The CRUD repository for accessing the database.</param>
/// <param name="mapper">The AutoMapper instance for mapping between DTOs and entity objects.</param>
public ReadService(TCRUDRepository repository, IMapper mapper)
{
_repository = repository;
_mapper = mapper;
}
/// <summary>
/// Asynchronously reads an entity by its identifier and maps it to a read DTO.
/// </summary>
/// <param name="id">The identifier of the entity to read.</param>
/// <returns>A service result indicating success or failure, including the read DTO if successful.</returns>
public virtual async Task<DataResult<TReadDto>> ReadByIdAsync(TId id)
{
var entity = await _repository.ReadByIdAsync(id);
return entity is null
? Result.Fail<TReadDto>()
: Result.Success(_mapper.Map<TReadDto>(entity));
}
/// <summary>
/// Asynchronously reads all entities and maps them to read DTOs.
/// </summary>
/// <returns>A service result including a collection of read DTOs.</returns>
public virtual async Task<DataResult<IEnumerable<TReadDto>>> ReadAllAsync()
{
var entities = await _repository.ReadAllAsync();
var readDto = _mapper.Map<IEnumerable<TReadDto>>(entities);
return Result.Success(readDto);
}
/// <summary>
/// Asynchronously deletes an entity by its identifier.
/// </summary>
/// <param name="id">The identifier of the entity to delete.</param>
/// <returns>A service message indicating success or failure.</returns>
public virtual async Task<Result> DeleteAsyncById(TId id)
{
TEntity? entity = await _repository.ReadByIdAsync(id);
if (entity is null)
return Result.Fail();
bool isDeleted = await _repository.DeleteAsync(entity);
return isDeleted ? Result.Success() : Result.Fail();
}
/// <summary>
/// Asynchronously checks if an entity with the specified identifier exists.
/// </summary>
/// <param name="id">The identifier of the entity to check.</param>
/// <returns>A Task that represents the asynchronous operation. The task result contains a boolean value indicating whether the entity exists.</returns>
public virtual async Task<bool> HasEntity(TId id) => await _repository.CountAsync(id) > 0;
}
}

View File

@@ -1,6 +1,9 @@
<?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' ">
<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')" />
</ImportGroup>
</Project>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1020 KiB

View File

@@ -1,44 +1,113 @@
using DigitalData.Core.Abstractions.Client;
using Microsoft.Extensions.Options;
using System.Diagnostics.CodeAnalysis;
using System.Net;
using System.Web;
namespace DigitalData.Core.Client
{
public class BaseHttpClientService : IBaseHttpClientService
{
protected readonly HttpClient _client;
protected readonly CookieContainer _cookies;
protected readonly CookieContainer _cookies;
[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;
_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(
string route = "",
string? scheme = null,
int? port = null,
string path = "",
IEnumerable<KeyValuePair<string, object?>>? queryParams = null,
HttpMethod? method = 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 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
method ??= HttpMethod.Get;
// create URL
var requestUriStr = Uri + route;
var requestUri = new Uri(requestUriStr);
var uriBuilder = new UriBuilder(_uri);
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
if (sendWithCookie)
@@ -56,7 +125,7 @@ namespace DigitalData.Core.Client
else if (body != null)
requestMessage.Content = body;
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);
@@ -68,5 +137,11 @@ namespace DigitalData.Core.Client
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 = '&';
}
}

View File

@@ -1,33 +1,35 @@
using DigitalData.Core.Abstractions.Client;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using System.Net;
namespace DigitalData.Core.Client
{
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<CookieContainer>();
services.AddSingleton<IBaseHttpClientService, BaseHttpClientService>();
services.Configure<HttpClientOptions>(opt => opt.Uri = uri);
return services;
}
public static IServiceCollection AddHttpClientService<TClientOptions>(this IServiceCollection services, Action<TClientOptions>? clientOptions = null, bool setAsDefaultBase = false)
where TClientOptions : HttpClientOptions
public static IServiceCollection AddHttpClientService<THttpClientOptions>(this IServiceCollection services, IConfigurationSection section)
where THttpClientOptions : class, IHttpClientOptions
{
services.TryAddSingleton<HttpClient>();
services.TryAddSingleton<CookieContainer>();
services.AddSingleton<IHttpClientService<TClientOptions>, HttpClientService<TClientOptions>>();
services.Configure(clientOptions ?? (_ => { }));
if (setAsDefaultBase)
services.AddSingleton<IBaseHttpClientService, HttpClientService<TClientOptions>>();
services.AddHttpClientServiceDefaults();
services.TryAddSingleton<IHttpClientService<THttpClientOptions>, HttpClientService<THttpClientOptions>>();
return services.Configure<THttpClientOptions>(section);
}
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;
}
}

View File

@@ -1,25 +1,35 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<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>
<PackageId>DigitalData.Core.Client</PackageId>
<Version>1.0.1.1</Version>
<Version>2.0.3</Version>
<Authors>Digital Data GmbH</Authors>
<Company>Digital Data GmbH</Company>
<Product>Digital Data GmbH</Product>
<Copyright>Copyright 2024</Copyright>
<PackageProjectUrl></PackageProjectUrl>
<PackageIcon>Assets\icon.png</PackageIcon>
<PackageIcon>core_icon.png</PackageIcon>
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
<PackageTags>digital data core http client json serilization</PackageTags>
<AssemblyVersion>2.0.3</AssemblyVersion>
<FileVersion>2.0.3</FileVersion>
</PropertyGroup>
<ItemGroup>
<None Include="..\..\nuget-package-icons\core_icon.png">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" 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" />
</ItemGroup>

View File

@@ -1,7 +0,0 @@
namespace DigitalData.Core.Client
{
public class HttpClientOptions
{
public string Uri { get; set; } = string.Empty;
}
}

View File

@@ -5,9 +5,9 @@ using System.Net;
namespace DigitalData.Core.Client
{
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)
{
}
}

View File

@@ -19,7 +19,7 @@ namespace DigitalData.Core.Client
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>>();
}
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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;
}
}
}

View File

@@ -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>

View File

@@ -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);
}
}

View File

@@ -1,12 +0,0 @@
{
"profiles": {
"DigitalData.Core.CultureServices": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:61600;http://localhost:61602"
}
}
}

View File

@@ -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);
}
}

View File

@@ -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": ""
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -1,4 +0,0 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v7.0", FrameworkDisplayName = ".NET 7.0")]

View File

@@ -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;

View File

@@ -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"
}
}
}
}
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -1,4 +0,0 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v7.0", FrameworkDisplayName = ".NET 7.0")]

View File

@@ -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 =

View File

@@ -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;

View File

@@ -1 +0,0 @@
36fef0fd26a832d2188715455582d92b1504d333459c8ca9de1908bace5726e0

View File

@@ -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

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1020 KiB

View File

@@ -1,23 +0,0 @@
using AutoMapper;
namespace DigitalData.Core.DTO
{
public static class AutoMapperExtension
{
[Obsolete("use mapper.Map<T>")]
/// <summary>
/// Maps a source object to a destination object, or throws an exception if the mapping result is null.
/// </summary>
/// <typeparam name="TSource">The source object type.</typeparam>
/// <typeparam name="TDestination">The destination object type.</typeparam>
/// <param name="source">The source object to map from.</param>
/// <returns>The mapped destination object.</returns>
/// <exception cref="MappingResultNullException">Thrown when the mapping result is null.</exception>
public static TDestination MapOrThrow<TDestination>(this IMapper mapper, object source)
{
return mapper.Map<TDestination>(source) ?? throw new AutoMapperMappingException(
$"Mapping to {typeof(TDestination).FullName} resulted in a null object. " +
"Hint: Ensure that the AutoMapper profile configuration for this mapping is correct.");
}
}
}

View File

@@ -147,6 +147,35 @@ namespace DigitalData.Core.DTO
/// <returns>True if any notice has any of the specified flags; otherwise, false.</returns>
public static bool HasAnyFlag(this IEnumerable<Notice> notices, params Enum[] flags) => flags.Any(f => notices.HasFlag(f));
/// <summary>
/// Executes a function based on the success or failure of the task result,
/// without using result data.
/// </summary>
/// <typeparam name="I">The type of the return value.</typeparam>
/// <param name="tResult">The task returning a result to evaluate.</param>
/// <param name="Success">The function to execute if the result is successful.</param>
/// <param name="Fail">The function to execute if the result is a failure.</param>
/// <returns>The result of the executed function.</returns>
public static I? Then<I>(this Result result, Func<I> Success)
{
return result.IsSuccess ? Success() : default;
}
/// <summary>
/// Executes a function based on the success or failure of the task result,
/// using the data in the result.
/// </summary>
/// <typeparam name="T">The type of the data in the result.</typeparam>
/// <typeparam name="I">The type of the return value.</typeparam>
/// <param name="tResult">The task returning a data result to evaluate.</param>
/// <param name="Success">The function to execute if the data result is successful.</param>
/// <param name="Fail">The function to execute if the data result is a failure.</param>
/// <returns>The result of the executed function.</returns>
public static async Task<I?> ThenAsync<I>(this Result result, Func<Task<I>> SuccessAsync)
{
return result.IsSuccess ? await SuccessAsync() : default;
}
/// <summary>
/// Executes a function based on the success or failure of the result.
/// </summary>

View File

@@ -1,24 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<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>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<PackageId>DigitalData.Core.DTO</PackageId>
<Version>1.0.0.1</Version>
<Version>2.0.0.0</Version>
<Authors>Digital Data GmbH</Authors>
<Company>Digital Data GmbH</Company>
<Product>DigitalData.Core.DTO</Product>
<Copyright>Copyright 2024</Copyright>
<PackageIcon>icon.png</PackageIcon>
<PackageIcon>core_icon.png</PackageIcon>
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
<PackageTags>digital data core dto clean architecture result pattern</PackageTags>
</PropertyGroup>
<ItemGroup>
<None Include="..\DigitalData.Core.Abstractions\Assets\icon.png">
<None Include="..\..\nuget-package-icons\core_icon.png">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1020 KiB

View File

@@ -1,4 +1,5 @@
using DigitalData.Core.Abstractions.Infrastructure;
using DigitalData.Core.Abstractions;
using DigitalData.Core.Abstractions.Infrastructure;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System.DirectoryServices;
@@ -17,7 +18,7 @@ namespace DigitalData.Core.Infrastructure
/// <param name="configureRepository">An optional action to configure additional services for the repository.</param>
/// <returns>The original <see cref="IServiceCollection"/> instance, allowing further configuration.</returns>
public static IServiceCollection AddCleanCRUDRepository<TEntity, TId, TDbContext, TCRUDRepository>(this IServiceCollection services, Action<IServiceCollection>? configureRepository = null)
where TCRUDRepository : CRUDRepository<TEntity, TId, TDbContext> where TEntity : class where TDbContext : DbContext
where TCRUDRepository : CRUDRepository<TEntity, TId, TDbContext> where TEntity : class, IUnique<TId> where TDbContext : DbContext
{
services.AddScoped<ICRUDRepository<TEntity, TId>, TCRUDRepository>();
configureRepository?.Invoke(services);

View File

@@ -1,25 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<PackageId>DigitalData.Core.Infrastructure</PackageId>
<Version>1.0.1.1</Version>
<Version>2.0.0.0</Version>
<Authors>Digital Data GmbH</Authors>
<Company>Digital Data GmbH</Company>
<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>
<Copyright>Copyright 2024</Copyright>
<PackageIcon>icon.png</PackageIcon>
<PackageIcon>core_icon.png</PackageIcon>
<RepositoryUrl>http://git.dd:3000/AppStd/WebCoreModules.git</RepositoryUrl>
<RepositoryType>digital data core abstractions clean architecture</RepositoryType>
<PackageTags>digital data core infrastructure clean architecture</PackageTags>
</PropertyGroup>
<ItemGroup>
<None Include="..\DigitalData.Core.Abstractions\Assets\icon.png">
<None Include="..\..\nuget-package-icons\core_icon.png">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>

View File

@@ -13,7 +13,10 @@
<SourceRoot Include="C:\Users\tekh\.nuget\packages\" />
<SourceRoot Include="D:\ProgramFiles\DevExpress 21.2\Components\Offline Packages\" />
</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')" />
</ImportGroup>
</Project>

View File

@@ -1,6 +1,9 @@
<?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' ">
<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')" />
</ImportGroup>
</Project>

View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\DigitalData.Core.Abstractions\DigitalData.Core.Abstractions.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,13 @@
namespace DigitalData.Core.Security.Extensions
{
public static class Extensions
{
public static string ToBase64String(this byte[] bytes) => Convert.ToBase64String(bytes);
public static byte[] Base64ToByte(this string base64String) => Convert.FromBase64String(base64String);
public static byte[] ToBytes(this string str) => System.Text.Encoding.UTF8.GetBytes(str);
public static string BytesToString(this byte[] bytes) => System.Text.Encoding.UTF8.GetString(bytes);
}
}

View File

@@ -0,0 +1,66 @@
using DigitalData.Core.Abstractions.Security;
using System.Collections.Concurrent;
using System.Security.Cryptography;
namespace DigitalData.Core.Security.Extensions
{
public static class RSAExtensions
{
public static RSA ToRSA(this string pem)
{
var rsa = RSA.Create();
rsa.ImportFromPem(pem);
return rsa;
}
public static IRSADecryptor GetRSADecryptor(this ICryptFactory factory, string issuer, string audience, Version? version = null, string? seperator = null)
=> factory[factory.RSAKeyNameFormatter(issuer, audience, true, version, seperator)];
public static bool TryGetRSADecryptor(this ICryptFactory factory, string issuer, string audience, out IRSADecryptor? decryptor, Version? version = null, string? seperator = null)
=> factory.TryGetRSADecryptor(factory.RSAKeyNameFormatter(issuer, audience, true, version, seperator), out decryptor);
private static string CreatePath(string filename, string? directory = null)
{
directory ??= Environment.CurrentDirectory;
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
return Path.Combine(directory, $"{filename}.pem");
}
private static readonly ConcurrentDictionary<string, SemaphoreSlim> FileLocks = new();
public static void SavePem(this IRSACryptographer decryptor, string key, string? directory = null)
{
var filePath = CreatePath(filename: key, directory : directory);
var fileLock = FileLocks.GetOrAdd(filePath, _ => new (1, 1));
fileLock.Wait();
try
{
File.WriteAllText(filePath, decryptor.Pem);
}
finally
{
fileLock.Release();
}
}
public static async Task SavePemAsync(this IRSACryptographer decryptor, string key, string? directory = null)
{
var filePath = CreatePath(filename: key, directory: directory);
var fileLock = FileLocks.GetOrAdd(filePath, _ => new (1, 1));
await fileLock.WaitAsync();
try
{
await File.WriteAllTextAsync(filePath, decryptor.Pem);
}
finally
{
fileLock.Release();
}
}
}
}

View File

@@ -0,0 +1,25 @@
using DigitalData.Core.Abstractions.Security;
using Microsoft.Extensions.Logging;
namespace DigitalData.Core.Security
{
public class CryptFactory : RSAFactory, ICryptFactory
{
private readonly IDictionary<string, IRSADecryptor> _decryptors;
public IRSADecryptor this[string key] { get => _decryptors[key]; set => _decryptors[key] = value; }
public Func<string, string, bool, Version?, string?, string> RSAKeyNameFormatter { get; }
public CryptFactory(ILogger<CryptFactory> logger, IDictionary<string, IRSADecryptor> decryptors, Func<string, string, bool, Version?, string?, string> rsaKeyNameFormatter) : base()
{
_decryptors = decryptors ?? new Dictionary<string, IRSADecryptor>();
RSAKeyNameFormatter = rsaKeyNameFormatter;
logger?.LogInformation("Core.Secrets version: {Version}, Created on: {CreationDate}.", Secrets.Version, Secrets.CreationDate.ToString("dd.MM.yyyy"));
}
public bool TryGetRSADecryptor(string key, out IRSADecryptor? decryptor) => _decryptors.TryGetValue(key, out decryptor);
}
}

View File

@@ -0,0 +1,16 @@
using DigitalData.Core.Abstractions.Security;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
namespace DigitalData.Core.Security
{
public static class DIExtensions
{
public static IServiceCollection AddSecurity(this IServiceCollection services)
{
services.TryAddScoped<ICryptFactory, CryptFactory>();
return services;
}
}
}

View File

@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\DigitalData.Core.Abstractions\DigitalData.Core.Abstractions.csproj" />
<ProjectReference Include="..\DigitalData.Core.Security.Extensions\DigitalData.Core.Security.Extensions.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,16 @@
using DigitalData.Core.Abstractions.Security;
using System.Security.Cryptography;
namespace DigitalData.Core.Security
{
public class RSACryptographer : IRSACryptographer
{
public required virtual string Pem { get; init; }
public RSAEncryptionPadding Padding { get; init; } = RSAEncryptionPadding.OaepSHA256;
protected virtual RSA RSA { get; } = RSA.Create();
internal RSACryptographer() { }
}
}

View File

@@ -0,0 +1,58 @@
using DigitalData.Core.Abstractions.Security;
using DigitalData.Core.Security.Extensions;
using System.Security.Cryptography;
namespace DigitalData.Core.Security
{
public class RSADecryptor : RSACryptographer, IRSADecryptor, IRSACryptographer
{
public (string Value, Version Version)? VersionedPassword
{
init
{
_password = value?.Value;
PasswordVersion = value?.Version;
}
}
private string? _password;
public Version? PasswordVersion { get; private init; } = null;
public bool HasEncryptedPem => _password is not null;
public bool IsEncrypted => _password is not null;
private readonly Lazy<IRSAEncryptor> _lazyEncryptor;
public IRSAEncryptor Encryptor => _lazyEncryptor.Value;
private readonly Lazy<RSA> lazyRSA;
protected override RSA RSA => lazyRSA.Value;
public RSADecryptor()
{
_lazyEncryptor = new(() => new RSAEncryptor()
{
Pem = RSA.ExportRSAPublicKeyPem(),
Padding = Padding
});
lazyRSA = new(() =>
{
var rsa = RSA.Create();
if (_password is null)
RSA.ImportFromPem(Pem);
else
RSA.ImportFromEncryptedPem(Pem, _password.AsSpan());
return rsa;
});
}
public byte[] Decrypt(byte[] data) => RSA.Decrypt(data, Padding);
public string Decrypt(string data) => RSA.Decrypt(data.Base64ToByte(), Padding).BytesToString();
}
}

View File

@@ -0,0 +1,24 @@
using DigitalData.Core.Abstractions.Security;
using DigitalData.Core.Security.Extensions;
namespace DigitalData.Core.Security
{
public class RSAEncryptor : RSACryptographer, IRSAEncryptor, IRSACryptographer
{
public override required string Pem
{
get => base.Pem;
init
{
RSA.ImportFromPem(base.Pem);
base.Pem = value;
}
}
public byte[] Encrypt(byte[] data) => RSA.Encrypt(data, Padding);
public string Encrypt(string data) => RSA.Encrypt(data.Base64ToByte(), Padding).BytesToString();
public bool Verify(string data, string signature) => Encrypt(data) == signature;
}
}

View File

@@ -0,0 +1,132 @@
using DigitalData.Core.Abstractions.Security;
using System.Security.Cryptography;
using System.Text;
namespace DigitalData.Core.Security
{
public class RSAFactory
{
private static readonly Lazy<RSAFactory> LazyInstance = new(() => new());
public static RSAFactory Static => LazyInstance.Value;
public static readonly string DefaultEncryptedPrivateKeyFileTag = "enc-private";
public static readonly string DefaultPrivateKeyFileTag = "private";
public static readonly string DefaultPublicKeyFileTag = "public";
public static readonly IEnumerable<string> KeyFileTags = new string[] { DefaultEncryptedPrivateKeyFileTag, DefaultPrivateKeyFileTag, DefaultPublicKeyFileTag };
private static readonly Lazy<IEnumerable<string>> LazyLowerFileTags = new(() => KeyFileTags.Select(tag => tag.ToLower()));
public static readonly string DefaultRSAKeyNameSeparator = "-_-";
//TODO: make the validation using regex
public static string DefaultRSAKeyNameFormatter(string issuer, string audience, bool isPrivate = true, Version? passwordVersion = null, string? separator = null)
{
separator ??= DefaultRSAKeyNameSeparator;
void ValidateForbidden(string value, string paramName)
{
if (Path.GetInvalidFileNameChars().Any(value.Contains) || LazyLowerFileTags.Value.Any(tag => value.ToLower().Contains(tag)))
throw new ArgumentException($"RSA decryptor key name creation is forbidden. The {paramName} contains forbidden characters that are not allowed in file naming.", paramName);
}
static void ValidateSeparator(string value, string paramName, string separator)
{
if (value.Contains(separator))
throw new ArgumentException($"RSA decryptor key name creation is forbidden. The {paramName} contains separator characters ({separator}) that are not allowed in file naming.", paramName);
}
ValidateForbidden(issuer, nameof(issuer));
ValidateForbidden(audience, nameof(audience));
ValidateForbidden(separator, nameof(separator));
ValidateSeparator(issuer, nameof(issuer), separator);
ValidateSeparator(audience, nameof(audience), separator);
var sb = new StringBuilder(issuer.Length + audience.Length + separator.Length * 2 + 20);
sb.Append(issuer).Append(separator).Append(audience).Append(separator);
if (passwordVersion is null && isPrivate)
sb.Append(DefaultPrivateKeyFileTag);
else if (isPrivate)
sb.Append(DefaultEncryptedPrivateKeyFileTag).Append(separator).Append(passwordVersion);
else if (passwordVersion is null)
sb.Append(DefaultPublicKeyFileTag);
else
sb.Append(DefaultPublicKeyFileTag).Append(separator).Append(passwordVersion);
return sb.ToString();
}
public int KeySizeInBits { get; init; } = 2048;
public string PbePassword { private get; init; } = Secrets.PBE_PASSWORD;
public PbeEncryptionAlgorithm PbeEncryptionAlgorithm { get; init; } = PbeEncryptionAlgorithm.Aes256Cbc;
public HashAlgorithmName PbeHashAlgorithmName { get; init; } = HashAlgorithmName.SHA256;
public int PbeIterationCount { get; init; } = 100_000;
private readonly Lazy<PbeParameters> _lazyPbeParameters;
public PbeParameters PbeParameters => _lazyPbeParameters.Value;
public string EncryptedPrivateKeyPemLabel { get; init; } = "ENCRYPTED PRIVATE KEY";
internal RSAFactory()
{
_lazyPbeParameters = new(() => new PbeParameters(PbeEncryptionAlgorithm, PbeHashAlgorithmName, PbeIterationCount));
}
public string CreateRSAPrivateKeyPem(int? keySizeInBits = null)
=> RSA.Create(keySizeInBits ?? KeySizeInBits).ExportRSAPrivateKeyPem();
public string CreateEncryptedPrivateKeyPem(
int? keySizeInBits = null,
string? password = null,
PbeEncryptionAlgorithm? pbeEncryptionAlgorithm = null,
HashAlgorithmName? hashAlgorithmName = null,
int? iterationCount = null)
{
password ??= PbePassword;
var pbeParameters = (pbeEncryptionAlgorithm is null && hashAlgorithmName is null && iterationCount is null)
? new PbeParameters(
pbeEncryptionAlgorithm ?? PbeEncryptionAlgorithm,
hashAlgorithmName ?? PbeHashAlgorithmName,
iterationCount ?? PbeIterationCount)
: PbeParameters;
var encryptedPrivateKey = RSA.Create(keySizeInBits ?? KeySizeInBits).ExportEncryptedPkcs8PrivateKey(password.AsSpan(), pbeParameters);
var pemChars = PemEncoding.Write(EncryptedPrivateKeyPemLabel, encryptedPrivateKey);
return new string(pemChars);
}
public async Task<IRSADecryptor> ReadRSADecryptorAsync(string path, Version? version = null, CancellationToken cancellationToken = default)
{
var pem = await File.ReadAllTextAsync(path, cancellationToken);
(string Value, Version Version)? versionedPassword = null;
if(version is not null)
{
if (version != Secrets.Version)
throw new InvalidOperationException($"The provided version {version} does not match the expected version {Secrets.Version}.");
versionedPassword = (Secrets.PBE_PASSWORD, Secrets.Version);
}
return new RSADecryptor()
{
Pem = pem,
VersionedPassword = versionedPassword
};
}
}
}

View 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-";
}
}

View File

@@ -2,7 +2,7 @@
using DigitalData.Core.Client;
using Microsoft.Extensions.DependencyInjection;
namespace DigitalData.Core.Tests
namespace DigitalData.Core.Tests.Client
{
[TestFixture]
public class BaseHttpClientServiceTests
@@ -14,22 +14,46 @@ namespace DigitalData.Core.Tests
public void SetUp()
{
_serviceProvider = new ServiceCollection()
.AddHttpClientService("https://jsonplaceholder.typicode.com/todos")
.AddHttpClientService("https://jsonplaceholder.typicode.com", "todos")
.BuildServiceProvider();
_service = _serviceProvider.GetRequiredService<IBaseHttpClientService>();
}
[Test]
public async Task FetchJsonAsync_ShouldReturnJsonResponse()
public async Task FetchJsonAsync_ShouldReturnJsonResponse_WithCorrectWithPath()
{
// 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(todo => todo.userId);
// Assert
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.");
}
}
}
}

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
@@ -26,6 +26,7 @@
<ProjectReference Include="..\DigitalData.Core.Client\DigitalData.Core.Client.csproj" />
<ProjectReference Include="..\DigitalData.Core.DTO\DigitalData.Core.DTO.csproj" />
<ProjectReference Include="..\DigitalData.Core.Infrastructure\DigitalData.Core.Infrastructure.csproj" />
<ProjectReference Include="..\DigitalData.Core.Security\DigitalData.Core.Security.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,7 @@
namespace DigitalData.Core.Tests.Security
{
[TestFixture]
public class RSADecryptorTests
{
}
}

View File

@@ -1,27 +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>
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)nunit3testadapter\4.3.0\build\netcoreapp2.1\NUnit3TestAdapter.props" Condition="Exists('$(NuGetPackageRoot)nunit3testadapter\4.3.0\build\netcoreapp2.1\NUnit3TestAdapter.props')" />
<Import Project="$(NuGetPackageRoot)nunit\3.13.3\build\NUnit.props" Condition="Exists('$(NuGetPackageRoot)nunit\3.13.3\build\NUnit.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.testplatform.testhost\17.3.2\build\netcoreapp2.1\Microsoft.TestPlatform.TestHost.props" Condition="Exists('$(NuGetPackageRoot)microsoft.testplatform.testhost\17.3.2\build\netcoreapp2.1\Microsoft.TestPlatform.TestHost.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.codecoverage\17.3.2\build\netstandard1.0\Microsoft.CodeCoverage.props" Condition="Exists('$(NuGetPackageRoot)microsoft.codecoverage\17.3.2\build\netstandard1.0\Microsoft.CodeCoverage.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.net.test.sdk\17.3.2\build\netcoreapp2.1\Microsoft.NET.Test.Sdk.props" Condition="Exists('$(NuGetPackageRoot)microsoft.net.test.sdk\17.3.2\build\netcoreapp2.1\Microsoft.NET.Test.Sdk.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>
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<PkgNUnit_Analyzers Condition=" '$(PkgNUnit_Analyzers)' == '' ">C:\Users\tekh\.nuget\packages\nunit.analyzers\3.5.0</PkgNUnit_Analyzers>
</PropertyGroup>
</Project>

View File

@@ -21,22 +21,28 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DigitalData.Core.Legacy.Tes
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DigitalData.Core.Legacy.Client", "DigitalData.Core.Legacy.Client\DigitalData.Core.Legacy.Client.csproj", "{E009A053-A9F4-48F2-984F-EF5C376A9B14}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DigitalData.Core.Security", "DigitalData.Core.Security\DigitalData.Core.Security.csproj", "{47D80C65-74A2-4EB8-96A5-D571A9108FB3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DigitalData.Core.Security.Extensions", "DigitalData.Core.Security.Extensions\DigitalData.Core.Security.Extensions.csproj", "{D740182D-82DA-480A-9F87-BFB4A8620A00}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DigitalData.Core.Terminal", "DigitalData.Core.Terminal\DigitalData.Core.Terminal.csproj", "{0FA93730-8084-4907-B172-87D610323796}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A765EBEA-3D1E-4F36-869B-6D72F87FF3F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A765EBEA-3D1E-4F36-869B-6D72F87FF3F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A765EBEA-3D1E-4F36-869B-6D72F87FF3F6}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{A765EBEA-3D1E-4F36-869B-6D72F87FF3F6}.Debug|Any CPU.Build.0 = Release|Any CPU
{A765EBEA-3D1E-4F36-869B-6D72F87FF3F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A765EBEA-3D1E-4F36-869B-6D72F87FF3F6}.Release|Any CPU.Build.0 = Release|Any CPU
{DB404CD9-CBB8-4771-AB1B-FD4FDE2C28CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DB404CD9-CBB8-4771-AB1B-FD4FDE2C28CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DB404CD9-CBB8-4771-AB1B-FD4FDE2C28CC}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{DB404CD9-CBB8-4771-AB1B-FD4FDE2C28CC}.Debug|Any CPU.Build.0 = Release|Any CPU
{DB404CD9-CBB8-4771-AB1B-FD4FDE2C28CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DB404CD9-CBB8-4771-AB1B-FD4FDE2C28CC}.Release|Any CPU.Build.0 = Release|Any CPU
{C57B2480-F632-4691-9C4C-8CC01237203C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C57B2480-F632-4691-9C4C-8CC01237203C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C57B2480-F632-4691-9C4C-8CC01237203C}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{C57B2480-F632-4691-9C4C-8CC01237203C}.Debug|Any CPU.Build.0 = Release|Any CPU
{C57B2480-F632-4691-9C4C-8CC01237203C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C57B2480-F632-4691-9C4C-8CC01237203C}.Release|Any CPU.Build.0 = Release|Any CPU
{B54DEF90-C30C-44EA-9875-76F1B330CBB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
@@ -47,11 +53,11 @@ Global
{0B051A5F-BD38-47D1-BAFF-D44BA30D3FB7}.Debug|Any CPU.Build.0 = Release|Any CPU
{0B051A5F-BD38-47D1-BAFF-D44BA30D3FB7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0B051A5F-BD38-47D1-BAFF-D44BA30D3FB7}.Release|Any CPU.Build.0 = Release|Any CPU
{6A80FFEC-9B83-40A7-8C78-124440B48B33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6A80FFEC-9B83-40A7-8C78-124440B48B33}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6A80FFEC-9B83-40A7-8C78-124440B48B33}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{6A80FFEC-9B83-40A7-8C78-124440B48B33}.Debug|Any CPU.Build.0 = Release|Any CPU
{6A80FFEC-9B83-40A7-8C78-124440B48B33}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6A80FFEC-9B83-40A7-8C78-124440B48B33}.Release|Any CPU.Build.0 = Release|Any CPU
{13E40DF1-6123-4838-9BF8-086C94E6ADF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{13E40DF1-6123-4838-9BF8-086C94E6ADF6}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{13E40DF1-6123-4838-9BF8-086C94E6ADF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{13E40DF1-6123-4838-9BF8-086C94E6ADF6}.Release|Any CPU.Build.0 = Release|Any CPU
{84B18026-F9A0-4366-BC69-1662D9E7342D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
@@ -62,6 +68,18 @@ Global
{E009A053-A9F4-48F2-984F-EF5C376A9B14}.Debug|Any CPU.Build.0 = Release|Any CPU
{E009A053-A9F4-48F2-984F-EF5C376A9B14}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E009A053-A9F4-48F2-984F-EF5C376A9B14}.Release|Any CPU.Build.0 = Release|Any CPU
{47D80C65-74A2-4EB8-96A5-D571A9108FB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{47D80C65-74A2-4EB8-96A5-D571A9108FB3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{47D80C65-74A2-4EB8-96A5-D571A9108FB3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{47D80C65-74A2-4EB8-96A5-D571A9108FB3}.Release|Any CPU.Build.0 = Release|Any CPU
{D740182D-82DA-480A-9F87-BFB4A8620A00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D740182D-82DA-480A-9F87-BFB4A8620A00}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D740182D-82DA-480A-9F87-BFB4A8620A00}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D740182D-82DA-480A-9F87-BFB4A8620A00}.Release|Any CPU.Build.0 = Release|Any CPU
{0FA93730-8084-4907-B172-87D610323796}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0FA93730-8084-4907-B172-87D610323796}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0FA93730-8084-4907-B172-87D610323796}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0FA93730-8084-4907-B172-87D610323796}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE