1
0
mirror of https://github.com/bitwarden/server.git synced 2024-11-22 12:15:36 +01:00

[PM-153] Extend Freshdesk integration (#2939)

* Move keys into FreshDeskSettings class

* Add configurable custom fields for user and org

In FreshDesk we currently use the custom fields `cf_user` and `cf_org`.

- For the US instance these will be set to those values.
- For the EU instance these will likely be configured to `cf_user_eu` and `cf_org_eu`

* Fix file encoding

* Add region to notes

* Use customizable org field value in condition check
This commit is contained in:
Daniel James Smith 2023-05-23 14:43:44 +02:00 committed by GitHub
parent a1fb847233
commit 09144ddb52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 11 deletions

View File

@ -8,8 +8,7 @@ public class BillingSettings
public virtual bool StripeEventParseThrowMismatch { get; set; } = true; public virtual bool StripeEventParseThrowMismatch { get; set; } = true;
public virtual string BitPayWebhookKey { get; set; } public virtual string BitPayWebhookKey { get; set; }
public virtual string AppleWebhookKey { get; set; } public virtual string AppleWebhookKey { get; set; }
public virtual string FreshdeskWebhookKey { get; set; } public virtual FreshDeskSettings FreshDesk { get; set; } = new FreshDeskSettings();
public virtual string FreshdeskApiKey { get; set; }
public virtual string FreshsalesApiKey { get; set; } public virtual string FreshsalesApiKey { get; set; }
public virtual PayPalSettings PayPal { get; set; } = new PayPalSettings(); public virtual PayPalSettings PayPal { get; set; } = new PayPalSettings();
@ -19,4 +18,16 @@ public class BillingSettings
public virtual string BusinessId { get; set; } public virtual string BusinessId { get; set; }
public virtual string WebhookKey { get; set; } public virtual string WebhookKey { get; set; }
} }
public class FreshDeskSettings
{
public virtual string ApiKey { get; set; }
public virtual string WebhookKey { get; set; }
/// <summary>
/// Indicates the data center region. Valid values are "US" and "EU"
/// </summary>
public virtual string Region { get; set; }
public virtual string UserFieldName { get; set; }
public virtual string OrgFieldName { get; set; }
}
} }

View File

@ -43,7 +43,7 @@ public class FreshdeskController : Controller
public async Task<IActionResult> PostWebhook([FromQuery, Required] string key, public async Task<IActionResult> PostWebhook([FromQuery, Required] string key,
[FromBody, Required] FreshdeskWebhookModel model) [FromBody, Required] FreshdeskWebhookModel model)
{ {
if (string.IsNullOrWhiteSpace(key) || !CoreHelpers.FixedTimeEquals(key, _billingSettings.FreshdeskWebhookKey)) if (string.IsNullOrWhiteSpace(key) || !CoreHelpers.FixedTimeEquals(key, _billingSettings.FreshDesk.WebhookKey))
{ {
return new BadRequestResult(); return new BadRequestResult();
} }
@ -60,13 +60,14 @@ public class FreshdeskController : Controller
var updateBody = new Dictionary<string, object>(); var updateBody = new Dictionary<string, object>();
var note = string.Empty; var note = string.Empty;
note += $"<li>Region: {_billingSettings.FreshDesk.Region}</li>";
var customFields = new Dictionary<string, object>(); var customFields = new Dictionary<string, object>();
var user = await _userRepository.GetByEmailAsync(ticketContactEmail); var user = await _userRepository.GetByEmailAsync(ticketContactEmail);
if (user != null) if (user != null)
{ {
var userLink = $"{_globalSettings.BaseServiceUri.Admin}/users/edit/{user.Id}"; var userLink = $"{_globalSettings.BaseServiceUri.Admin}/users/edit/{user.Id}";
note += $"<li>User, {user.Email}: {userLink}</li>"; note += $"<li>User, {user.Email}: {userLink}</li>";
customFields.Add("cf_user", userLink); customFields.Add(_billingSettings.FreshDesk.UserFieldName, userLink);
var tags = new HashSet<string>(); var tags = new HashSet<string>();
if (user.Premium) if (user.Premium)
{ {
@ -79,13 +80,13 @@ public class FreshdeskController : Controller
var orgNote = $"{org.Name} ({org.Seats.GetValueOrDefault()}): " + var orgNote = $"{org.Name} ({org.Seats.GetValueOrDefault()}): " +
$"{_globalSettings.BaseServiceUri.Admin}/organizations/edit/{org.Id}"; $"{_globalSettings.BaseServiceUri.Admin}/organizations/edit/{org.Id}";
note += $"<li>Org, {orgNote}</li>"; note += $"<li>Org, {orgNote}</li>";
if (!customFields.Any(kvp => kvp.Key == "cf_org")) if (!customFields.Any(kvp => kvp.Key == _billingSettings.FreshDesk.OrgFieldName))
{ {
customFields.Add("cf_org", orgNote); customFields.Add(_billingSettings.FreshDesk.OrgFieldName, orgNote);
} }
else else
{ {
customFields["cf_org"] += $"\n{orgNote}"; customFields[_billingSettings.FreshDesk.OrgFieldName] += $"\n{orgNote}";
} }
var planName = GetAttribute<DisplayAttribute>(org.PlanType).Name.Split(" ").FirstOrDefault(); var planName = GetAttribute<DisplayAttribute>(org.PlanType).Name.Split(" ").FirstOrDefault();
@ -145,7 +146,7 @@ public class FreshdeskController : Controller
{ {
try try
{ {
var freshdeskAuthkey = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{_billingSettings.FreshdeskApiKey}:X")); var freshdeskAuthkey = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{_billingSettings.FreshDesk.ApiKey}:X"));
var httpClient = _httpClientFactory.CreateClient("FreshdeskApi"); var httpClient = _httpClientFactory.CreateClient("FreshdeskApi");
request.Headers.Add("Authorization", $"Basic {freshdeskAuthkey}"); request.Headers.Add("Authorization", $"Basic {freshdeskAuthkey}");
var response = await httpClient.SendAsync(request); var response = await httpClient.SendAsync(request);

View File

@ -69,6 +69,12 @@
"production": false, "production": false,
"businessId": "AD3LAUZSNVPJY", "businessId": "AD3LAUZSNVPJY",
"webhookKey": "SECRET" "webhookKey": "SECRET"
},
"freshdesk": {
"apiKey": "SECRET",
"webhookKey": "SECRET",
"userFieldName": "cf_user",
"orgFieldName": "cf_org"
} }
} }
} }

View File

@ -19,6 +19,9 @@ public class FreshdeskControllerTests
private const string ApiKey = "TESTFRESHDESKAPIKEY"; private const string ApiKey = "TESTFRESHDESKAPIKEY";
private const string WebhookKey = "TESTKEY"; private const string WebhookKey = "TESTKEY";
private const string UserFieldName = "cf_user";
private const string OrgFieldName = "cf_org";
[Theory] [Theory]
[BitAutoData((string)null, null)] [BitAutoData((string)null, null)]
[BitAutoData((string)null)] [BitAutoData((string)null)]
@ -26,7 +29,7 @@ public class FreshdeskControllerTests
public async Task PostWebhook_NullRequiredParameters_BadRequest(string freshdeskWebhookKey, FreshdeskWebhookModel model, public async Task PostWebhook_NullRequiredParameters_BadRequest(string freshdeskWebhookKey, FreshdeskWebhookModel model,
BillingSettings billingSettings, SutProvider<FreshdeskController> sutProvider) BillingSettings billingSettings, SutProvider<FreshdeskController> sutProvider)
{ {
sutProvider.GetDependency<IOptions<BillingSettings>>().Value.FreshdeskWebhookKey.Returns(billingSettings.FreshdeskWebhookKey); sutProvider.GetDependency<IOptions<BillingSettings>>().Value.FreshDesk.WebhookKey.Returns(billingSettings.FreshDesk.WebhookKey);
var response = await sutProvider.Sut.PostWebhook(freshdeskWebhookKey, model); var response = await sutProvider.Sut.PostWebhook(freshdeskWebhookKey, model);
@ -52,8 +55,10 @@ public class FreshdeskControllerTests
sutProvider.GetDependency<IHttpClientFactory>().CreateClient("FreshdeskApi").Returns(httpClient); sutProvider.GetDependency<IHttpClientFactory>().CreateClient("FreshdeskApi").Returns(httpClient);
sutProvider.GetDependency<IOptions<BillingSettings>>().Value.FreshdeskWebhookKey.Returns(WebhookKey); sutProvider.GetDependency<IOptions<BillingSettings>>().Value.FreshDesk.WebhookKey.Returns(WebhookKey);
sutProvider.GetDependency<IOptions<BillingSettings>>().Value.FreshdeskApiKey.Returns(ApiKey); sutProvider.GetDependency<IOptions<BillingSettings>>().Value.FreshDesk.ApiKey.Returns(ApiKey);
sutProvider.GetDependency<IOptions<BillingSettings>>().Value.FreshDesk.UserFieldName.Returns(UserFieldName);
sutProvider.GetDependency<IOptions<BillingSettings>>().Value.FreshDesk.OrgFieldName.Returns(OrgFieldName);
var response = await sutProvider.Sut.PostWebhook(WebhookKey, model); var response = await sutProvider.Sut.PostWebhook(WebhookKey, model);