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 { /// /// Simple based wrapper around /// [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"; /// public HttpClient Client { get; private set; } /// /// Constructor for . /// /// instance passed by DI injection /// instance passed by DI injection. public PwnedBreachService( HttpClient httpClient, IOptions 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); } /// public Task> GetBreachesByAccountAsync(string emailAccount, bool unVerified = false, bool fullResponse = true, string domain = "", CancellationToken token = default) { var args = new Dictionary(); //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>(url, token); } /// public Task> GetAllBreachesAsync(string domain = "", CancellationToken token = default) { var args = new Dictionary(); //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>(url, token); } /// public Task> GetAllDataClassesAsync(CancellationToken token = default) { //https://haveibeenpwned.com/api/v2/dataclasses var url = $"{_options.ServiceApiUrl}{_getAllDataClasses}"; return GetRequestAsync>(url, token); } /// public Task> 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>(url, token); } private async Task GetRequestAsync(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(result); } } }