diff --git a/DummyClient/DummyClient.csproj b/DummyClient/DummyClient.csproj index 6c218fbb2f85b3b34dce23b65399f248a2677605..e449bbc26417523e8a0a2dc0ac0878d7f2f50811 100644 --- a/DummyClient/DummyClient.csproj +++ b/DummyClient/DummyClient.csproj @@ -9,7 +9,7 @@ </PropertyGroup> <ItemGroup> - <ProjectReference Include="..\FitConnect\FitConnect.csproj" /> + <ProjectReference Include="..\FitConnect\FitConnect.csproj"/> </ItemGroup> </Project> diff --git a/DummyClient/Program.cs b/DummyClient/Program.cs index 57dbaecde832102c4e4f52b9f8dea18eb4efa3b5..ec14319dbb2488d2e6d1dcbb01fdf9a3f5242adf 100644 --- a/DummyClient/Program.cs +++ b/DummyClient/Program.cs @@ -91,7 +91,7 @@ async Task DetailSubscriberCall() { Console.WriteLine( "This is a dummy client to demonstrate the usage of the FitConnect SDK for .NET"); -_logger = new Microsoft.Extensions.Logging.Logger<System.AppDomain>(new NullLoggerFactory()); +_logger = new Logger<AppDomain>(new NullLoggerFactory()); client = new Client(FitConnectEndpoints.Create(FitConnectEndpoints.EndpointType.Development), logger: _logger); diff --git a/E2ETests/SenderTest.cs b/E2ETests/SenderTest.cs index d86d35219bbfc4e4aab3668a1a626253a4ab41bd..2cc48c1e4cce3d58baca1da3d230752bff83d0c0 100644 --- a/E2ETests/SenderTest.cs +++ b/E2ETests/SenderTest.cs @@ -1,11 +1,8 @@ using System; using System.IO; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; using FitConnect; using FitConnect.Security; using FluentAssertions; -using Microsoft.IdentityModel.Tokens; using Newtonsoft.Json; using NUnit.Framework; diff --git a/FitConnect/BaseClasses/FunctionalBaseClass.cs b/FitConnect/BaseClasses/FunctionalBaseClass.cs index 66618c66575042020f98f0ed16db7f1111be8414..c6f90e785a4841e7a9563feddc95961636e928de 100644 --- a/FitConnect/BaseClasses/FunctionalBaseClass.cs +++ b/FitConnect/BaseClasses/FunctionalBaseClass.cs @@ -8,7 +8,8 @@ using Microsoft.Extensions.Logging; namespace FitConnect.BaseClasses; public abstract class FunctionalBaseClass { - // protected readonly FitConnectApiService ApiService; + public X509Certificate2 Certificate { get; } + // protected readonly FitConnectApiService ApiService; protected IOAuthService OAuthService; protected ISubmissionService SubmissionService; @@ -16,8 +17,6 @@ public abstract class FunctionalBaseClass { public readonly IEncryption Encryption; protected readonly ILogger? Logger; - protected readonly X509Certificate2 Certificate; - internal Client Owner { get; set; } /// <summary> @@ -35,6 +34,7 @@ public abstract class FunctionalBaseClass { IOAuthService oAuthService, ISubmissionService submissionService, IRouteService routeService) { + Certificate = certificate; Endpoints = endpoints ?? FitConnectEndpoints.Create(FitConnectEndpoints.EndpointType.Development); @@ -42,15 +42,16 @@ public abstract class FunctionalBaseClass { OAuthService = oAuthService; SubmissionService = submissionService; RouteService = routeService; - Certificate = certificate; Encryption = new RsaEncryption(logger, certificate); } + internal Client Owner { get; set; } + public FitConnectEndpoints Endpoints { get; } /// <summary> - /// Requesting the OAuth-Token + /// Requesting the OAuth-Token /// </summary> /// <param name="clientId"></param> /// <param name="clientSecret"></param> diff --git a/FitConnect/Client.cs b/FitConnect/Client.cs index 81bceacda7d913b7f6fe2e2917c8a580604e2c79..4def29224d5161ba5481e13feac9e0199c64bc03 100644 --- a/FitConnect/Client.cs +++ b/FitConnect/Client.cs @@ -11,13 +11,10 @@ namespace FitConnect; /// </summary> // ReSharper disable once UnusedType.Global public class Client { + private readonly X509Certificate2? _receiverCertificate; + private readonly X509Certificate2? _senderCertificate; internal string? ClientId; internal string? ClientSecret; - private readonly X509Certificate2? _senderCertificate; - private readonly X509Certificate2? _receiverCertificate; - - public FluentSender Sender { get; } - public FluentSubscriber Subscriber { get; } /// <summary> /// FitConnect Client @@ -51,6 +48,9 @@ public class Client { _receiverCertificate, logger) { Owner = this }; } + public FluentSender Sender { get; } + public FluentSubscriber Subscriber { get; } + /// <summary> /// Get destination for submission. @@ -144,4 +144,4 @@ public class Client { int limit = 100) { return GetSubmissionsAsync(destinationId, offset, limit).Result; } -} +} \ No newline at end of file diff --git a/FitConnect/FluentSender.cs b/FitConnect/FluentSender.cs index 3f49cafd311fedabe8d305e861f214d11babca12..cc32adba9da80992f16f854e37a01be18e311da9 100644 --- a/FitConnect/FluentSender.cs +++ b/FitConnect/FluentSender.cs @@ -47,10 +47,14 @@ public class FluentSender : Sender, IFluentApi<FluentSender> { public CreateSubmissionDto? NewSubmission { get; set; } public Submission Submission { get; set; } - public static Sender Create() { - throw new NotImplementedException(); - } + /// <summary> + /// Authenticates with the FitConnect API. + /// </summary> + /// <param name="clientId">The client id from the submission service</param> + /// <param name="clientSecret">The client secret</param> + /// <param name="scope">Optional scope for the credentials</param> + /// <returns></returns> public FluentSender Authenticate(string clientId, string clientSecret, string? scope = null) { if (_nextStep != State.Authenticate) throw new InvalidOperationException( @@ -65,12 +69,12 @@ public class FluentSender : Sender, IFluentApi<FluentSender> { } /// <summary> - /// Creates a new <see cref="Submission"/> on the FitConnect server. + /// Creates a new <see cref="Submission" /> on the FitConnect server. /// </summary> - /// <param name="submission"></param> + /// <param name="submission" cref="Submission">The <see cref="Submission"/> body to be sent</param> /// <returns></returns> - /// <exception cref="InvalidOperationException"></exception> - /// <exception cref="ArgumentException"></exception> + /// <exception cref="InvalidOperationException">If sender is not authenticated</exception> + /// <exception cref="ArgumentException">If submission is not ready to be sent</exception> public FluentSender CreateSubmission(Submission submission) { if (_nextStep != State.CreateSubmission) throw new InvalidOperationException( @@ -97,6 +101,11 @@ public class FluentSender : Sender, IFluentApi<FluentSender> { } + /// <summary> + /// Posts the <see cref="Attachment"/>s to the FitConnect API. The attachment ids are sent with creating the submission. + /// </summary> + /// <returns></returns> + /// <exception cref="InvalidOperationException"></exception> public FluentSender UploadAttachments() { if (_nextStep != State.UploadAttachments) throw new InvalidOperationException( @@ -113,6 +122,17 @@ public class FluentSender : Sender, IFluentApi<FluentSender> { return this; } + /// <summary> + /// Sending the submission and finishing the process. + /// <para> + /// Finishing the submission by transmitting <see cref="Metadata"/> and <see cref="Data"/>. + /// </para> + /// </summary> + /// <param name="metadata"></param> + /// <param name="data"></param> + /// <returns></returns> + /// <remarks>This call finishes the submission process</remarks> + /// <exception cref="InvalidOperationException"></exception> public FluentSender SendSubmission(Metadata metadata, Data? data = null) { if (_nextStep != State.SendSubmission) throw new InvalidOperationException( diff --git a/FitConnect/Models/Callback.cs b/FitConnect/Models/Callback.cs index 4967c9f885c5a8df711ce1384e8d676e2435b959..3bf0bba58a76f17a072094a045a61afb0dc908e6 100644 --- a/FitConnect/Models/Callback.cs +++ b/FitConnect/Models/Callback.cs @@ -4,10 +4,10 @@ namespace FitConnect.Models; public record Callback(string? Url, string? Secret) { public static explicit operator Callback(CallbackDto dto) { - return new(dto.Url, null); + return new Callback(dto.Url, null); } public static explicit operator CallbackDto(Callback model) { - return new() { Url = model.Url }; + return new CallbackDto { Url = model.Url }; } } diff --git a/FitConnect/Models/FitConnectException.cs b/FitConnect/Models/FitConnectException.cs index 70fecf2f3bf2e3888512c0837561e9f98401d5db..91ca6c592ae3525804d42abe2e2e3a576ab3173a 100644 --- a/FitConnect/Models/FitConnectException.cs +++ b/FitConnect/Models/FitConnectException.cs @@ -1,17 +1,17 @@ namespace FitConnect.Models; /// <summary> -/// Representation of FitConnect error responses +/// Representation of FitConnect error responses /// </summary> public class FitConnectException : Exception { public enum ErrorTypeEnum { - Unknown, + Unknown } - public ErrorTypeEnum ErrorType { get; set; } - public FitConnectException(string message, ErrorTypeEnum errorType = ErrorTypeEnum.Unknown, Exception? innerException = null) : base(message, innerException) { ErrorType = errorType; } + + public ErrorTypeEnum ErrorType { get; set; } } diff --git a/FitConnect/Models/Metadata.cs b/FitConnect/Models/Metadata.cs index c9b798a0cc8f1bbcdae795cf166d42bccede59cd..c0e78ec823a152a02f94e4168e734e2b5e1051cc 100644 --- a/FitConnect/Models/Metadata.cs +++ b/FitConnect/Models/Metadata.cs @@ -1,5 +1,4 @@ using System.Security.Cryptography.X509Certificates; -using FitConnect.Models; namespace FitConnect.Models; @@ -13,7 +12,6 @@ public class Metadata : IEncrypt { } } - public class Data : IEncrypt { public string Encrypt(PublicKey publicKey) { return ""; diff --git a/FitConnect/Models/ServiceType.cs b/FitConnect/Models/ServiceType.cs index aee540c41d4e5ab046c98d4f913040843db4c074..270aac944633df1257cd4889be64e8c5b211b312 100644 --- a/FitConnect/Models/ServiceType.cs +++ b/FitConnect/Models/ServiceType.cs @@ -9,7 +9,7 @@ public class ServiceType { public string? Identifier { get; set; } public static explicit operator ServiceType(ServiceTypeDto dto) { - return new() { + return new ServiceType { Description = dto.Description, Identifier = dto.Identifier, Name = dto.Name @@ -17,13 +17,14 @@ public class ServiceType { } public static explicit operator ServiceTypeDto(ServiceType model) { - return new() { + return new ServiceTypeDto { Description = model.Description, Identifier = model.Identifier, Name = model.Name }; } - public bool IsValid() => - (!string.IsNullOrWhiteSpace(Name)) && (!string.IsNullOrWhiteSpace(Identifier)); + public bool IsValid() { + return !string.IsNullOrWhiteSpace(Name) && !string.IsNullOrWhiteSpace(Identifier); + } } diff --git a/FitConnect/Models/Submission.cs b/FitConnect/Models/Submission.cs index fea7227af4a8d8f16031a6fb48aa386037aa70bf..d8cb6cfdf6d2d3c439c7dd32ff4da26d554e9cae 100644 --- a/FitConnect/Models/Submission.cs +++ b/FitConnect/Models/Submission.cs @@ -1,4 +1,3 @@ -using System.Security.Cryptography.X509Certificates; using FitConnect.Services.Models; namespace FitConnect.Models; @@ -31,14 +30,14 @@ public class Submission { public ServiceType ServiceType { get; init; } public Callback? Callback { get; set; } + public Metadata Metadata { get; set; } + public Data? Data { get; set; } public bool IsSubmissionReadyToAdd(out string? error) { var innerError = ""; if (string.IsNullOrEmpty(DestinationId)) innerError += "DestinationId is required\r\n"; - if (ServiceType.IsValid()) { - innerError += "ServiceType is invalid\r\n"; - } + if (ServiceType.IsValid()) innerError += "ServiceType is invalid\r\n"; if (string.IsNullOrWhiteSpace(innerError)) { error = null; @@ -53,16 +52,8 @@ public class Submission { return true; } - - /// <summary> - /// Fachdaten - /// </summary> - public Data? Data { get; set; } - - public Metadata Metadata { get; set; } - public static explicit operator Submission(SubmissionForPickupDto dto) { - return new() { + return new Submission { Id = dto.SubmissionId, Callback = null, DestinationId = dto.DestinationId, @@ -71,7 +62,7 @@ public class Submission { } public static explicit operator Submission(SubmissionDto dto) { - return new() { + return new Submission { Id = dto.SubmissionId, Callback = (Callback)dto.Callback, DestinationId = dto.DestinationId, @@ -80,7 +71,7 @@ public class Submission { } public static explicit operator CreateSubmissionDto(Submission sub) { - return new() { + return new CreateSubmissionDto { AnnouncedAttachments = sub.Attachments.Select(a => a.Id).ToList(), DestinationId = sub.DestinationId, ServiceType = (ServiceTypeDto)sub.ServiceType, diff --git a/FitConnect/Sender.cs b/FitConnect/Sender.cs index 4e2b70c144f2cd3a49822797df9530581bcbb2bc..d5a3257f8431c9dfea38804aedf6a3cc32ae7a3a 100644 --- a/FitConnect/Sender.cs +++ b/FitConnect/Sender.cs @@ -1,4 +1,5 @@ -using System.Security.Cryptography.X509Certificates; +using System.Runtime.ConstrainedExecution; +using System.Security.Cryptography.X509Certificates; using Autofac; using FitConnect.BaseClasses; using FitConnect.Models; @@ -8,10 +9,10 @@ using Microsoft.Extensions.Logging; namespace FitConnect; -public partial class Sender : FunctionalBaseClass { +public class Sender : FunctionalBaseClass { internal Sender(FitConnectEndpoints endpoints, X509Certificate2 certificate, - IOAuthService oAuthService, + IOAuthService oAuthService, ISubmissionService submissionService, IRouteService routeService, ILogger? logger = null @@ -20,7 +21,7 @@ public partial class Sender : FunctionalBaseClass { } public static Sender Create(FitConnectEndpoints endpoints, - X509Certificate2 certificate,ILogger? logger = null) { + X509Certificate2 certificate, ILogger? logger = null) { var container = DiContainer.GetContainer(endpoints, certificate, null, logger); return container.Resolve<Sender>(); } @@ -78,14 +79,16 @@ public partial class Sender : FunctionalBaseClass { } /// <summary> - /// Encrypt attachments (Anhänge) + /// Encrypt attachments (Anhänge) /// </summary> /// <param name="publicKey">Public key for encryption</param> /// <param name="attachments">List of attachments to encrypt</param> /// <returns></returns> public Dictionary<string, string> - Encrypt(PublicKey publicKey, IEnumerable<Attachment> attachments) => - attachments.Select(a => Encrypt(publicKey, a)).ToDictionary(p => p.Key, p => p.Value); + Encrypt(PublicKey publicKey, IEnumerable<Attachment> attachments) { + return attachments.Select(a => Encrypt(publicKey, a)) + .ToDictionary(p => p.Key, p => p.Value); + } /// <summary> /// Create Metadata incl. Hash @@ -98,7 +101,7 @@ public partial class Sender : FunctionalBaseClass { } public CreateSubmissionDto AddSubmission(Submission submission) { - return new() { + return new CreateSubmissionDto { DestinationId = submission.DestinationId, ServiceType = (ServiceTypeDto)submission.ServiceType, AnnouncedAttachments = submission.Attachments.Select(a => a.Id).ToList() @@ -106,7 +109,7 @@ public partial class Sender : FunctionalBaseClass { } /// <summary> - /// Uploading the encrypted data to the server + /// Uploading the encrypted data to the server /// </summary> /// <param name="encryptedAttachments">Encrypted attachments with id and content</param> /// <exception cref="NotImplementedException"></exception> @@ -126,7 +129,7 @@ public partial class Sender : FunctionalBaseClass { /// <summary> - /// Encrypt Metadata with public key + /// Encrypt Metadata with public key /// </summary> /// <param name="publicKey"></param> /// <param name="metadata"></param> @@ -137,7 +140,7 @@ public partial class Sender : FunctionalBaseClass { } /// <summary> - /// Encrypt data with public key (Fachdaten) + /// Encrypt data with public key (Fachdaten) /// </summary> /// <param name="publicKey"></param> /// <param name="data"></param> @@ -148,7 +151,7 @@ public partial class Sender : FunctionalBaseClass { } /// <summary> - /// Uploading the encrypted data and metadata to the server + /// Uploading the encrypted data and metadata to the server /// </summary> /// <param name="encryptedData"></param> /// <param name="encryptedMetadata"></param> @@ -158,9 +161,9 @@ public partial class Sender : FunctionalBaseClass { } protected SubmitSubmissionDto CreateSubmitSubmissionDto(Submission submission) { - return new() { - EncryptedData = submission.Data?.Encrypt(this.Certificate.PublicKey), - EncryptedMetadata = submission.Metadata.Encrypt(Certificate.PublicKey), + return new SubmitSubmissionDto { + EncryptedData = submission.Data?.Encrypt(Certificate.PublicKey), + EncryptedMetadata = submission.Metadata.Encrypt(Certificate.PublicKey) }; } } diff --git a/Models/Models.csproj b/Models/Models.csproj index 245b8c8d902f44288fb973cbc21b2653b5342dcf..c3f983307e4fb2fce2affff62f544c9513ec0847 100644 --- a/Models/Models.csproj +++ b/Models/Models.csproj @@ -8,7 +8,7 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> + <PackageReference Include="Newtonsoft.Json" Version="13.0.1"/> </ItemGroup> </Project>