diff --git a/MessagingService.DataTransferObjects/MessagingService.DataTransferObjects.csproj b/MessagingService.DataTransferObjects/MessagingService.DataTransferObjects.csproj index dd1ef0a..7792513 100644 --- a/MessagingService.DataTransferObjects/MessagingService.DataTransferObjects.csproj +++ b/MessagingService.DataTransferObjects/MessagingService.DataTransferObjects.csproj @@ -4,4 +4,8 @@ net5.0;netstandard2.0 + + + + diff --git a/MessagingService.DataTransferObjects/SendEmailRequest.cs b/MessagingService.DataTransferObjects/SendEmailRequest.cs index 3db3859..25d0152 100644 --- a/MessagingService.DataTransferObjects/SendEmailRequest.cs +++ b/MessagingService.DataTransferObjects/SendEmailRequest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; + using Newtonsoft.Json; [ExcludeFromCodeCoverage] public class SendEmailRequest @@ -15,6 +16,7 @@ public class SendEmailRequest /// /// The message identifier. /// + [JsonProperty("message_id")] public Guid? MessageId { get; set; } /// @@ -23,6 +25,7 @@ public class SendEmailRequest /// /// The body. /// + [JsonProperty("body")] public String Body { get; set; } /// @@ -31,6 +34,7 @@ public class SendEmailRequest /// /// The connection identifier. /// + [JsonProperty("connection_identifier")] public Guid ConnectionIdentifier { get; set; } /// @@ -39,6 +43,7 @@ public class SendEmailRequest /// /// From address. /// + [JsonProperty("from_address")] public String FromAddress { get; set; } /// @@ -47,6 +52,7 @@ public class SendEmailRequest /// /// true if this instance is HTML; otherwise, false. /// + [JsonProperty("is_html")] public Boolean IsHtml { get; set; } /// @@ -55,6 +61,7 @@ public class SendEmailRequest /// /// The subject. /// + [JsonProperty("subject")] public String Subject { get; set; } /// @@ -63,6 +70,7 @@ public class SendEmailRequest /// /// To addresses. /// + [JsonProperty("to_addresses")] public List ToAddresses { get; set; } #endregion diff --git a/MessagingService.DataTransferObjects/SendEmailResponse.cs b/MessagingService.DataTransferObjects/SendEmailResponse.cs index 91808b4..737b780 100644 --- a/MessagingService.DataTransferObjects/SendEmailResponse.cs +++ b/MessagingService.DataTransferObjects/SendEmailResponse.cs @@ -2,6 +2,7 @@ { using System; using System.Diagnostics.CodeAnalysis; + using Newtonsoft.Json; /// /// @@ -17,6 +18,7 @@ public class SendEmailResponse /// /// The message identifier. /// + [JsonProperty("message_id")] public Guid MessageId { get; set; } #endregion diff --git a/MessagingService.DataTransferObjects/SendSMSRequest.cs b/MessagingService.DataTransferObjects/SendSMSRequest.cs index 963643c..eb6b15e 100644 --- a/MessagingService.DataTransferObjects/SendSMSRequest.cs +++ b/MessagingService.DataTransferObjects/SendSMSRequest.cs @@ -1,8 +1,9 @@ namespace MessagingService.DataTransferObjects { + using Newtonsoft.Json; using System; using System.Diagnostics.CodeAnalysis; - + [ExcludeFromCodeCoverage] public class SendSMSRequest { @@ -14,6 +15,7 @@ public class SendSMSRequest /// /// The connection identifier. /// + [JsonProperty("connection_identifier")] public Guid ConnectionIdentifier { get; set; } /// @@ -22,6 +24,7 @@ public class SendSMSRequest /// /// The destination. /// + [JsonProperty("destination")] public String Destination { get; set; } /// @@ -30,6 +33,7 @@ public class SendSMSRequest /// /// The message. /// + [JsonProperty("message")] public String Message { get; set; } /// @@ -38,6 +42,7 @@ public class SendSMSRequest /// /// The message identifier. /// + [JsonProperty("message_id")] public Guid? MessageId { get; set; } /// @@ -46,6 +51,7 @@ public class SendSMSRequest /// /// The sender. /// + [JsonProperty("sender")] public String Sender { get; set; } #endregion diff --git a/MessagingService.DataTransferObjects/SendSMSResponse.cs b/MessagingService.DataTransferObjects/SendSMSResponse.cs index bdd191f..9649a57 100644 --- a/MessagingService.DataTransferObjects/SendSMSResponse.cs +++ b/MessagingService.DataTransferObjects/SendSMSResponse.cs @@ -2,6 +2,7 @@ { using System; using System.Diagnostics.CodeAnalysis; + using Newtonsoft.Json; [ExcludeFromCodeCoverage] public class SendSMSResponse @@ -14,6 +15,7 @@ public class SendSMSResponse /// /// The message identifier. /// + [JsonProperty("message_id")] public Guid MessageId { get; set; } #endregion diff --git a/MessagingService.Tests/General/BootstrapperTests.cs b/MessagingService.Tests/General/BootstrapperTests.cs index c8882ed..77dddf4 100644 --- a/MessagingService.Tests/General/BootstrapperTests.cs +++ b/MessagingService.Tests/General/BootstrapperTests.cs @@ -56,6 +56,7 @@ private IConfigurationRoot SetupMemoryConfiguration() configuration.Add("SecurityConfiguration:Authority", "http://localhost"); configuration.Add("AppSettings:EmailProxy", "UnitTest"); configuration.Add("AppSettings:SMSProxy", "UnitTest"); + configuration.Add("AppSettings:ApiVersion", "1.0.0"); builder.AddInMemoryCollection(configuration); diff --git a/MessagingService/Common/ConfigureSwaggerOptions.cs b/MessagingService/Common/ConfigureSwaggerOptions.cs index a4c4479..08e9364 100644 --- a/MessagingService/Common/ConfigureSwaggerOptions.cs +++ b/MessagingService/Common/ConfigureSwaggerOptions.cs @@ -63,17 +63,13 @@ private static OpenApiInfo CreateInfoForApiVersion(ApiVersionDescription descrip { OpenApiInfo info = new OpenApiInfo { - Title = "Golf Handicapping API", + Title = "Messaging API", Version = description.ApiVersion.ToString(), - Description = "A REST Api to manage the golf club handicapping system.", + Description = "A REST Api to manage sending of various messages over different formats, currently only Email and SMS are supported.", Contact = new OpenApiContact { Name = "Stuart Ferguson", Email = "golfhandicapping@btinternet.com" - }, - License = new OpenApiLicense - { - Name = "TODO" } }; diff --git a/MessagingService/Common/RequestExamples/ExampleData.cs b/MessagingService/Common/RequestExamples/ExampleData.cs new file mode 100644 index 0000000..2595c2f --- /dev/null +++ b/MessagingService/Common/RequestExamples/ExampleData.cs @@ -0,0 +1,86 @@ +namespace MessagingService.Common.RequestExamples +{ + using System; + using System.Diagnostics.CodeAnalysis; + + /// + /// + /// + [ExcludeFromCodeCoverage] + internal static class ExampleData + { + #region Fields + + /// + /// The connection identifier + /// + internal static Guid ConnectionIdentifier = Guid.Parse("A6080219-E243-48F8-A6C3-D79610A74A5B"); + + /// + /// The email message from address + /// + internal static String EmailMessageFromAddress = "fromaddress@exampleemail.com"; + + /// + /// The email message HTML body + /// + internal static String EmailMessageHtmlBody = "

This is a test message body

"; + + /// + /// The email message identifier + /// + internal static Guid EmailMessageId = Guid.Parse("63BDE20F-28E0-4698-AF46-923A08198994"); + + /// + /// The email message is HTML + /// + internal static Boolean EmailMessageIsHtml = true; + + /// + /// The email message plain text body + /// + internal static String EmailMessagePlainTextBody = "This is a test message body"; + + /// + /// The email message plain text is HTML + /// + internal static Boolean EmailMessagePlainTextIsHtml = false; + + /// + /// The email message subject + /// + internal static String EmailMessageSubject = "Email Subject"; + + /// + /// The email message to address1 + /// + internal static String EmailMessageToAddress1 = "toaddress1@exampleemail.com"; + + /// + /// The email message to address2 + /// + internal static String EmailMessageToAddress2 = "toaddress2@exampleemail.com"; + + /// + /// The SMS message destination + /// + internal static String SMSMessageDestination = "07123456789"; + + /// + /// The SMS message identifier + /// + internal static Guid SMSMessageId = Guid.Parse("D38E20B1-64F1-4217-B192-24123862FE10"); + + /// + /// The SMS message message + /// + internal static String SMSMessageMessage = "Test SMS Message"; + + /// + /// The SMS message sender + /// + internal static String SMSMessageSender = "07000000001"; + + #endregion + } +} \ No newline at end of file diff --git a/MessagingService/Common/RequestExamples/SendEmailRequestExample.cs b/MessagingService/Common/RequestExamples/SendEmailRequestExample.cs new file mode 100644 index 0000000..afe684c --- /dev/null +++ b/MessagingService/Common/RequestExamples/SendEmailRequestExample.cs @@ -0,0 +1,69 @@ +namespace MessagingService.Common.RequestExamples +{ + using System; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using DataTransferObjects; + using Swashbuckle.AspNetCore.Filters; + + /// + /// + /// + /// + [ExcludeFromCodeCoverage] + public class SendEmailRequestExample : IMultipleExamplesProvider + { + #region Methods + + /// + /// Gets the examples. + /// + /// + public IEnumerable> GetExamples() + { + SendEmailRequest htmlEmailRequest = new SendEmailRequest + { + Body = ExampleData.EmailMessageHtmlBody, + ConnectionIdentifier = ExampleData.ConnectionIdentifier, + FromAddress = ExampleData.EmailMessageFromAddress, + ToAddresses = new List + { + ExampleData.EmailMessageToAddress1, + ExampleData.EmailMessageToAddress2 + }, + IsHtml = ExampleData.EmailMessageIsHtml, + MessageId = ExampleData.EmailMessageId, + Subject = ExampleData.EmailMessageSubject + }; + + SendEmailRequest plainTextEmailRequest = new SendEmailRequest + { + Body = ExampleData.EmailMessagePlainTextBody, + ConnectionIdentifier = ExampleData.ConnectionIdentifier, + FromAddress = ExampleData.EmailMessageFromAddress, + ToAddresses = new List + { + ExampleData.EmailMessageToAddress1, + ExampleData.EmailMessageToAddress2 + }, + IsHtml = ExampleData.EmailMessagePlainTextIsHtml, + MessageId = ExampleData.EmailMessageId, + Subject = ExampleData.EmailMessageSubject + }; + List> examples = new List>(); + examples.Add(new SwaggerExample + { + Name = "Html Email Request", + Value = htmlEmailRequest + }); + examples.Add(new SwaggerExample + { + Name = "Plan Text Email Request", + Value = plainTextEmailRequest + }); + return examples; + } + + #endregion + } +} \ No newline at end of file diff --git a/MessagingService/Common/RequestExamples/SendEmailResponseExample.cs b/MessagingService/Common/RequestExamples/SendEmailResponseExample.cs new file mode 100644 index 0000000..86f9a81 --- /dev/null +++ b/MessagingService/Common/RequestExamples/SendEmailResponseExample.cs @@ -0,0 +1,30 @@ +namespace MessagingService.Common.RequestExamples +{ + using System.Diagnostics.CodeAnalysis; + using DataTransferObjects; + using Swashbuckle.AspNetCore.Filters; + + /// + /// + /// + /// + [ExcludeFromCodeCoverage] + public class SendEmailResponseExample : IExamplesProvider + { + #region Methods + + /// + /// Gets the examples. + /// + /// + public SendEmailResponse GetExamples() + { + return new SendEmailResponse + { + MessageId = ExampleData.EmailMessageId + }; + } + + #endregion + } +} \ No newline at end of file diff --git a/MessagingService/Common/RequestExamples/SendSMSRequestExample.cs b/MessagingService/Common/RequestExamples/SendSMSRequestExample.cs new file mode 100644 index 0000000..09623a6 --- /dev/null +++ b/MessagingService/Common/RequestExamples/SendSMSRequestExample.cs @@ -0,0 +1,30 @@ +namespace MessagingService.Common.RequestExamples +{ + using System.Diagnostics.CodeAnalysis; + using DataTransferObjects; + using Swashbuckle.AspNetCore.Filters; + + /// + /// + /// + /// + [ExcludeFromCodeCoverage] + public class SendSMSRequestExample : IExamplesProvider + { + /// + /// Gets the examples. + /// + /// + public SendSMSRequest GetExamples() + { + return new SendSMSRequest + { + ConnectionIdentifier = ExampleData.ConnectionIdentifier, + MessageId = ExampleData.SMSMessageId, + Destination = ExampleData.SMSMessageDestination, + Message = ExampleData.SMSMessageMessage, + Sender = ExampleData.SMSMessageSender + }; + } + } +} \ No newline at end of file diff --git a/MessagingService/Common/RequestExamples/SendSMSResponseExample.cs b/MessagingService/Common/RequestExamples/SendSMSResponseExample.cs new file mode 100644 index 0000000..3c5a635 --- /dev/null +++ b/MessagingService/Common/RequestExamples/SendSMSResponseExample.cs @@ -0,0 +1,30 @@ +namespace MessagingService.Common.RequestExamples +{ + using System.Diagnostics.CodeAnalysis; + using DataTransferObjects; + using Swashbuckle.AspNetCore.Filters; + + /// + /// + /// + /// + [ExcludeFromCodeCoverage] + public class SendSMSResponseExample : IExamplesProvider + { + #region Methods + + /// + /// Gets the examples. + /// + /// + public SendSMSResponse GetExamples() + { + return new SendSMSResponse + { + MessageId = ExampleData.SMSMessageId + }; + } + + #endregion + } +} \ No newline at end of file diff --git a/MessagingService/Controllers/EmailController.cs b/MessagingService/Controllers/EmailController.cs index 6332b7a..dddafe5 100644 --- a/MessagingService/Controllers/EmailController.cs +++ b/MessagingService/Controllers/EmailController.cs @@ -7,11 +7,14 @@ namespace MessagingService.Controllers using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Threading.Tasks; - using BusinessLogic.Requests; using Common; + using Common.RequestExamples; using MediatR; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; + using Swashbuckle.AspNetCore.Annotations; + using Swashbuckle.AspNetCore.Filters; + using SendEmailRequest = BusinessLogic.Requests.SendEmailRequest; /// /// @@ -20,7 +23,6 @@ namespace MessagingService.Controllers [ExcludeFromCodeCoverage] [Route(EmailController.ControllerRoute)] [ApiController] - [ApiVersion("1.0")] [Authorize] public class EmailController : ControllerBase { @@ -56,6 +58,9 @@ public EmailController(IMediator mediator) /// [HttpPost] [Route("")] + [SwaggerResponse(201, "Created", typeof(SendEmailResponseDTO))] + [SwaggerResponseExample(201, typeof(SendEmailResponseExample))] + public async Task PostEmail([FromBody] SendEmailRequestDTO sendEmailRequest, CancellationToken cancellationToken) { diff --git a/MessagingService/Controllers/SMSController.cs b/MessagingService/Controllers/SMSController.cs index f40a5af..aee6efb 100644 --- a/MessagingService/Controllers/SMSController.cs +++ b/MessagingService/Controllers/SMSController.cs @@ -5,15 +5,17 @@ using System.Threading; using System.Threading.Tasks; using Common; + using Common.RequestExamples; using DataTransferObjects; using MediatR; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; + using Swashbuckle.AspNetCore.Annotations; + using Swashbuckle.AspNetCore.Filters; [ExcludeFromCodeCoverage] [Route(SMSController.ControllerRoute)] [ApiController] - [ApiVersion("1.0")] [Authorize] public class SMSController : ControllerBase { @@ -49,6 +51,8 @@ public SMSController(IMediator mediator) /// [HttpPost] [Route("")] + [SwaggerResponse(201, "Created", typeof(SendSMSResponse))] + [SwaggerResponseExample(201, typeof(SendSMSResponseExample))] public async Task PostSMS([FromBody] SendSMSRequest sendSMSRequest, CancellationToken cancellationToken) { diff --git a/MessagingService/MessagingService.csproj b/MessagingService/MessagingService.csproj index 346e1cb..7486a24 100644 --- a/MessagingService/MessagingService.csproj +++ b/MessagingService/MessagingService.csproj @@ -12,6 +12,8 @@ + + diff --git a/MessagingService/Startup.cs b/MessagingService/Startup.cs index 05e9cb6..3b2be2d 100644 --- a/MessagingService/Startup.cs +++ b/MessagingService/Startup.cs @@ -40,6 +40,7 @@ namespace MessagingService using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using NLog.Extensions.Logging; + using NuGet.Versioning; using Service.Services.Email.IntegrationTest; using Service.Services.SMSServices.IntegrationTest; using Shared.DomainDrivenDesign.EventSourcing; @@ -233,12 +234,14 @@ private void ConfigureMiddlewareServices(IServiceCollection services) failureStatus: HealthStatus.Unhealthy, tags: new string[] { "db", "eventstore" }); + var version = ConfigurationReader.GetValue("AppSettings", "ApiVersion"); + var v = NuGetVersion.Parse(version); services.AddApiVersioning( options => { // reporting api versions will return the headers "api-supported-versions" and "api-deprecated-versions" options.ReportApiVersions = true; - options.DefaultApiVersion = new ApiVersion(1, 0); + options.DefaultApiVersion = new ApiVersion(v.Major, v.Minor, $"Patch{v.Patch}"); options.AssumeDefaultVersionWhenUnspecified = true; options.ApiVersionReader = new HeaderApiVersionReader("api-version"); }); diff --git a/MessagingService/appsettings.json b/MessagingService/appsettings.json index 9271831..eb6b45d 100644 --- a/MessagingService/appsettings.json +++ b/MessagingService/appsettings.json @@ -21,6 +21,7 @@ "EstateReportingReadModel": "server=localhost;user id=sa;password=sp1ttal;database=EstateReportingReadModel" }, "AppSettings": { + "ApiVersion": "1.0.9", "SubscriptionFilter": "Messaging", "UseConnectionStringConfig": false, "SecurityService": "http://192.168.1.133:5001",