gehgassi_backend/gehGassi.Pwned/PwnedBreachService.cs

138 lines
5.2 KiB
C#

using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using gehGassi.Pwned.Models;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
namespace gehGassi.Pwned
{
/// <summary>
/// Simple <see cref="HttpClient"/> based wrapper around <see cref="!:https://haveibeenpwned.com/API/"/>
/// </summary>
[ExcludeFromCodeCoverage]
public class PwnedBreachService : IPwnedBreachService
{
private readonly PwnedOptions _options;
private readonly string _getBreachesByAccountUri = "breachedaccount";
private readonly string _getAllBreachesUri = "breaches";
private readonly string _getAllDataClasses = "dataclasses";
private readonly string _getPastAccount = "pasteaccount";
///<inheritdoc/>
public HttpClient Client { get; private set; }
/// <summary>
/// Constructor for <see cref="PwnedBreachService"/>.
/// </summary>
/// <param name="httpClient"><see cref="HttpClient"/> instance passed by DI injection</param>
/// <param name="options"><see cref="IOptions{TOptions}"/> instance passed by DI injection.</param>
public PwnedBreachService(
HttpClient httpClient,
IOptions<PwnedOptions> options)
{
_options = options.Value;
Client = httpClient ?? throw new System.ArgumentNullException(nameof(httpClient));
var userAgent = $"{nameof(PwnedBreachService)}-kdcllc";
if (!string.IsNullOrEmpty(_options?.UserAgent))
{
userAgent = _options?.UserAgent;
}
httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
httpClient.DefaultRequestHeaders.Add("User-Agent", userAgent);
httpClient.DefaultRequestHeaders.Add("api-version", _options.ServiceApiVersion);
}
///<inheritdoc/>
public Task<List<Breach>> GetBreachesByAccountAsync(string emailAccount,
bool unVerified = false,
bool fullResponse = true,
string domain = "",
CancellationToken token = default)
{
var args = new Dictionary<string, string>();
//https://haveibeenpwned.com/api/v2/breachedaccount/test@example.com
var url = $"{_options.ServiceApiUrl}{_getBreachesByAccountUri}/{WebUtility.UrlEncode(emailAccount)}";
if (unVerified)
{
//https://haveibeenpwned.com/api/v2/breachedaccount/test@example.com?includeUnverified=true
args.Add("includeUnverified", unVerified.ToString());
}
if (!fullResponse)
{
//https://haveibeenpwned.com/api/v2/breachedaccount/test@example.com?truncateResponse=true
args.Add("truncateResponse", fullResponse.ToString());
}
if (!string.IsNullOrEmpty(domain))
{
//https://haveibeenpwned.com/api/v2/breachedaccount/test@example.com?domain=adobe.com
args.Add("domain", domain);
}
if (unVerified || !fullResponse || !string.IsNullOrEmpty(domain))
{
url = QueryHelpers.AddQueryString(url, args);
}
return GetRequestAsync<List<Breach>>(url, token);
}
///<inheritdoc/>
public Task<List<Breach>> GetAllBreachesAsync(string domain = "",
CancellationToken token = default)
{
var args = new Dictionary<string, string>();
//https://haveibeenpwned.com/api/v2/breaches
var url = $"{_options.ServiceApiUrl}{_getAllBreachesUri}";
if (!string.IsNullOrEmpty(domain))
{
//https://haveibeenpwned.com/api/v2/breaches?domain=adobe.com
args.Add("domain", WebUtility.UrlEncode(domain));
url = QueryHelpers.AddQueryString(url, args);
}
return GetRequestAsync<List<Breach>>(url, token);
}
///<inheritdoc/>
public Task<List<string>> GetAllDataClassesAsync(CancellationToken token = default)
{
//https://haveibeenpwned.com/api/v2/dataclasses
var url = $"{_options.ServiceApiUrl}{_getAllDataClasses}";
return GetRequestAsync<List<string>>(url, token);
}
///<inheritdoc/>
public Task<List<PastAccount>> GetPastByAccountAsync(string emailAccount,
CancellationToken token = default)
{
//https://haveibeenpwned.com/api/v2/pasteaccount/test@example.com
var url = $"{_options.ServiceApiUrl}{_getPastAccount}/{WebUtility.UrlEncode(emailAccount)}";
return GetRequestAsync<List<PastAccount>>(url, token);
}
private async Task<T> GetRequestAsync<T>(string url,
CancellationToken token = default)
{
var request = new HttpRequestMessage(HttpMethod.Get, url);
var response = await Client.SendAsync(request, token).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(result);
}
}
}