diff --git a/src/Billing/Controllers/FreshdeskController.cs b/src/Billing/Controllers/FreshdeskController.cs index 40c9c39d95..3b7415121e 100644 --- a/src/Billing/Controllers/FreshdeskController.cs +++ b/src/Billing/Controllers/FreshdeskController.cs @@ -144,7 +144,7 @@ public class FreshdeskController : Controller [HttpPost("webhook-onyx-ai")] public async Task PostWebhookOnyxAi([FromQuery, Required] string key, - [FromBody, Required] FreshdeskWebhookModel model) + [FromBody, Required] FreshdeskOnyxAiWebhookModel model) { // ensure that the key is from Freshdesk if (!IsValidRequestFromFreshdesk(key)) @@ -152,28 +152,8 @@ public class FreshdeskController : Controller return new BadRequestResult(); } - // get ticket info from Freshdesk - var getTicketRequest = new HttpRequestMessage(HttpMethod.Get, - string.Format("https://bitwarden.freshdesk.com/api/v2/tickets/{0}", model.TicketId)); - var getTicketResponse = await CallFreshdeskApiAsync(getTicketRequest); - - // check if we have a valid response from freshdesk - if (getTicketResponse.StatusCode != System.Net.HttpStatusCode.OK) - { - _logger.LogError("Error getting ticket info from Freshdesk. Ticket Id: {0}. Status code: {1}", - model.TicketId, getTicketResponse.StatusCode); - return BadRequest("Failed to retrieve ticket info from Freshdesk"); - } - - // extract info from the response - var ticketInfo = await ExtractTicketInfoFromResponse(getTicketResponse); - if (ticketInfo == null) - { - return BadRequest("Failed to extract ticket info from Freshdesk response"); - } - // create the onyx `answer-with-citation` request - var onyxRequestModel = new OnyxAnswerWithCitationRequestModel(ticketInfo.DescriptionText); + var onyxRequestModel = new OnyxAnswerWithCitationRequestModel(model.TicketDescriptionText); var onyxRequest = new HttpRequestMessage(HttpMethod.Post, string.Format("{0}/query/answer-with-citation", _billingSettings.Onyx.BaseUrl)) { @@ -249,29 +229,6 @@ public class FreshdeskController : Controller } } - private async Task ExtractTicketInfoFromResponse(HttpResponseMessage getTicketResponse) - { - var responseString = string.Empty; - try - { - responseString = await getTicketResponse.Content.ReadAsStringAsync(); - var ticketInfo = JsonSerializer.Deserialize(responseString, - options: new System.Text.Json.JsonSerializerOptions - { - PropertyNameCaseInsensitive = true, - }); - - return ticketInfo; - } - catch (System.Exception ex) - { - _logger.LogError("Error deserializing ticket info from Freshdesk response. Response: {0}. Exception {1}", - responseString, ex.ToString()); - } - - return null; - } - private async Task CallFreshdeskApiAsync(HttpRequestMessage request, int retriedCount = 0) { try diff --git a/src/Billing/Models/FreshdeskViewTicketModel.cs b/src/Billing/Models/FreshdeskViewTicketModel.cs deleted file mode 100644 index e4d485072c..0000000000 --- a/src/Billing/Models/FreshdeskViewTicketModel.cs +++ /dev/null @@ -1,47 +0,0 @@ -// FIXME: Update this file to be null safe and then delete the line below -#nullable disable - -namespace Bit.Billing.Models; - -using System; -using System.Collections.Generic; -using System.Text.Json.Serialization; - -public class FreshdeskViewTicketModel -{ - [JsonPropertyName("spam")] - public bool? Spam { get; set; } - - [JsonPropertyName("priority")] - public int? Priority { get; set; } - - [JsonPropertyName("source")] - public int? Source { get; set; } - - [JsonPropertyName("status")] - public int? Status { get; set; } - - [JsonPropertyName("subject")] - public string Subject { get; set; } - - [JsonPropertyName("support_email")] - public string SupportEmail { get; set; } - - [JsonPropertyName("id")] - public int Id { get; set; } - - [JsonPropertyName("description")] - public string Description { get; set; } - - [JsonPropertyName("description_text")] - public string DescriptionText { get; set; } - - [JsonPropertyName("created_at")] - public DateTime CreatedAt { get; set; } - - [JsonPropertyName("updated_at")] - public DateTime UpdatedAt { get; set; } - - [JsonPropertyName("tags")] - public List Tags { get; set; } -} diff --git a/src/Billing/Models/FreshdeskWebhookModel.cs b/src/Billing/Models/FreshdeskWebhookModel.cs index 19c94d5eba..aac0e9339d 100644 --- a/src/Billing/Models/FreshdeskWebhookModel.cs +++ b/src/Billing/Models/FreshdeskWebhookModel.cs @@ -16,3 +16,9 @@ public class FreshdeskWebhookModel [JsonPropertyName("ticket_tags")] public string TicketTags { get; set; } } + +public class FreshdeskOnyxAiWebhookModel : FreshdeskWebhookModel +{ + [JsonPropertyName("ticket_description_text")] + public string TicketDescriptionText { get; set; } +} diff --git a/test/Billing.Test/Controllers/FreshdeskControllerTests.cs b/test/Billing.Test/Controllers/FreshdeskControllerTests.cs index 90f8a09ea0..f0a34ff232 100644 --- a/test/Billing.Test/Controllers/FreshdeskControllerTests.cs +++ b/test/Billing.Test/Controllers/FreshdeskControllerTests.cs @@ -112,7 +112,7 @@ public class FreshdeskControllerTests [BitAutoData((string)null)] [BitAutoData(WebhookKey, null)] public async Task PostWebhookOnyxAi_InvalidWebhookKey_results_in_BadRequest( - string freshdeskWebhookKey, FreshdeskWebhookModel model, + string freshdeskWebhookKey, FreshdeskOnyxAiWebhookModel model, BillingSettings billingSettings, SutProvider sutProvider) { sutProvider.GetDependency>() @@ -124,59 +124,11 @@ public class FreshdeskControllerTests Assert.Equal(StatusCodes.Status400BadRequest, statusCodeResult.StatusCode); } - [Theory] - [BitAutoData(WebhookKey)] - public async Task PostWebhookOnyxAi_invalid_ticketid_results_in_BadRequest( - string freshdeskWebhookKey, FreshdeskWebhookModel model, SutProvider sutProvider) - { - sutProvider.GetDependency>() - .Value.FreshDesk.WebhookKey.Returns(freshdeskWebhookKey); - - var mockHttpMessageHandler = Substitute.ForPartsOf(); - var mockResponse = new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest); - mockHttpMessageHandler.Send(Arg.Any(), Arg.Any()) - .Returns(mockResponse); - var httpClient = new HttpClient(mockHttpMessageHandler); - - sutProvider.GetDependency().CreateClient("FreshdeskApi").Returns(httpClient); - - var response = await sutProvider.Sut.PostWebhookOnyxAi(freshdeskWebhookKey, model); - - var result = Assert.IsAssignableFrom(response); - Assert.Equal(StatusCodes.Status400BadRequest, result.StatusCode); - } - - [Theory] - [BitAutoData(WebhookKey)] - public async Task PostWebhookOnyxAi_invalid_freshdesk_response_results_in_BadRequest( - string freshdeskWebhookKey, FreshdeskWebhookModel model, - SutProvider sutProvider) - { - sutProvider.GetDependency>() - .Value.FreshDesk.WebhookKey.Returns(freshdeskWebhookKey); - - var mockHttpMessageHandler = Substitute.ForPartsOf(); - var mockResponse = new HttpResponseMessage(System.Net.HttpStatusCode.OK) - { - Content = new StringContent("non json content. expect json deserializer to throw error") - }; - mockHttpMessageHandler.Send(Arg.Any(), Arg.Any()) - .Returns(mockResponse); - var httpClient = new HttpClient(mockHttpMessageHandler); - - sutProvider.GetDependency().CreateClient("FreshdeskApi").Returns(httpClient); - - var response = await sutProvider.Sut.PostWebhookOnyxAi(freshdeskWebhookKey, model); - - var result = Assert.IsAssignableFrom(response); - Assert.Equal(StatusCodes.Status400BadRequest, result.StatusCode); - } - [Theory] [BitAutoData(WebhookKey)] public async Task PostWebhookOnyxAi_invalid_onyx_response_results_in_BadRequest( - string freshdeskWebhookKey, FreshdeskWebhookModel model, - FreshdeskViewTicketModel freshdeskTicketInfo, SutProvider sutProvider) + string freshdeskWebhookKey, FreshdeskOnyxAiWebhookModel model, + SutProvider sutProvider) { var billingSettings = sutProvider.GetDependency>().Value; billingSettings.FreshDesk.WebhookKey.Returns(freshdeskWebhookKey); @@ -184,12 +136,6 @@ public class FreshdeskControllerTests // mocking freshdesk Api request for ticket info var mockFreshdeskHttpMessageHandler = Substitute.ForPartsOf(); - var mockFreshdeskResponse = new HttpResponseMessage(System.Net.HttpStatusCode.OK) - { - Content = new StringContent(JsonSerializer.Serialize(freshdeskTicketInfo)) - }; - mockFreshdeskHttpMessageHandler.Send(Arg.Any(), Arg.Any()) - .Returns(mockFreshdeskResponse); var freshdeskHttpClient = new HttpClient(mockFreshdeskHttpMessageHandler); // mocking Onyx api response given a ticket description @@ -211,8 +157,7 @@ public class FreshdeskControllerTests [Theory] [BitAutoData(WebhookKey)] public async Task PostWebhookOnyxAi_success( - string freshdeskWebhookKey, FreshdeskWebhookModel model, - FreshdeskViewTicketModel freshdeskTicketInfo, + string freshdeskWebhookKey, FreshdeskOnyxAiWebhookModel model, OnyxAnswerWithCitationResponseModel onyxResponse, SutProvider sutProvider) { @@ -220,18 +165,8 @@ public class FreshdeskControllerTests billingSettings.FreshDesk.WebhookKey.Returns(freshdeskWebhookKey); billingSettings.Onyx.BaseUrl.Returns("http://simulate-onyx-api.com/api"); - // mocking freshdesk Api request for ticket info (GET) - var mockFreshdeskHttpMessageHandler = Substitute.ForPartsOf(); - var mockFreshdeskResponse = new HttpResponseMessage(System.Net.HttpStatusCode.OK) - { - Content = new StringContent(JsonSerializer.Serialize(freshdeskTicketInfo)) - }; - mockFreshdeskHttpMessageHandler.Send( - Arg.Is(_ => _.Method == HttpMethod.Get), - Arg.Any()) - .Returns(mockFreshdeskResponse); - // mocking freshdesk api add note request (POST) + var mockFreshdeskHttpMessageHandler = Substitute.ForPartsOf(); var mockFreshdeskAddNoteResponse = new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest); mockFreshdeskHttpMessageHandler.Send( Arg.Is(_ => _.Method == HttpMethod.Post),