diff --git a/Source/StrongGrid.IntegrationTests/Tests/WebhookSettings.cs b/Source/StrongGrid.IntegrationTests/Tests/WebhookSettings.cs index 57718f48..aee2cfb8 100644 --- a/Source/StrongGrid.IntegrationTests/Tests/WebhookSettings.cs +++ b/Source/StrongGrid.IntegrationTests/Tests/WebhookSettings.cs @@ -12,26 +12,26 @@ public async Task RunAsync(IBaseClient client, TextWriter log, CancellationToken await log.WriteLineAsync("\n***** WEBHOOK SETTINGS *****\n").ConfigureAwait(false); - // GET THE EVENT SETTINGS - var eventWebhookSettings = await client.WebhookSettings.GetEventWebhookSettingsAsync(null, cancellationToken).ConfigureAwait(false); - await log.WriteLineAsync("The event webhook settings have been retrieved.").ConfigureAwait(false); + // GET ALL THE EVENT SETTINGS + var eventWebhookSettings = await client.WebhookSettings.GetAllEventWebhookSettingsAsync(null, cancellationToken).ConfigureAwait(false); + await log.WriteLineAsync($"All the event webhook settings have been retrieved. There are {eventWebhookSettings.Length} configured events.").ConfigureAwait(false); - // GET THE INBOUND PARSE SETTINGS + // GET ALL THE INBOUND PARSE SETTINGS var inboundParseWebhookSettings = await client.WebhookSettings.GetAllInboundParseWebhookSettingsAsync(null, cancellationToken).ConfigureAwait(false); - await log.WriteLineAsync("The inbound parse webhook settings have been retrieved.").ConfigureAwait(false); + await log.WriteLineAsync($"All the inbound parse webhook settings have been retrieved. There are {inboundParseWebhookSettings.Length} configured inbound parse.").ConfigureAwait(false); // GET THE SIGNED EVENTS PUBLIC KEY - var publicKey = await client.WebhookSettings.GetSignedEventsPublicKeyAsync(cancellationToken).ConfigureAwait(false); + var publicKey = await client.WebhookSettings.GetSignedEventsPublicKeyAsync(null, cancellationToken).ConfigureAwait(false); await log.WriteLineAsync($"The signed events public key is: {publicKey}").ConfigureAwait(false); // ================================================== // DEBUGGING - //const string desiredUrl = "https://4934-2001-18c0-41d-f200-ac79-2199-f1fc-c831.ngrok.io/StrongGrid"; + //const string desiredUrl = "https://3928-2001-18c0-41c-3f00-00-632b.ngrok-free.app/StrongGrid"; //const string inboundHostName = "api.stronggrid.com"; // Uncomment the following line to configure all webhook events to be sent to your desired URL - //var updatedEventWebhookSettings = await client.WebhookSettings.UpdateEventWebhookSettingsAsync(true, desiredUrl, true, true, true, true, true, true, true, true, true, true, true, null, cancellationToken).ConfigureAwait(false); + //var updatedEventWebhookSettings = await client.WebhookSettings.UpdateEventWebhookSettingsAsync(true, desiredUrl, true, true, true, true, true, true, true, true, true, true, true, "My friendly Name", null, null, null, null, cancellationToken).ConfigureAwait(false); // Uncomment the following line to receive a sample webhook at your desired URL //await client.WebhookSettings.SendEventTestAsync(desiredUrl).ConfigureAwait(false); diff --git a/Source/StrongGrid.UnitTests/Resources/WebhookSettingsTests.cs b/Source/StrongGrid.UnitTests/Resources/WebhookSettingsTests.cs index efd1813e..50fc73f8 100644 --- a/Source/StrongGrid.UnitTests/Resources/WebhookSettingsTests.cs +++ b/Source/StrongGrid.UnitTests/Resources/WebhookSettingsTests.cs @@ -149,6 +149,7 @@ public async Task UpdateEventWebhookSettingsAsync() var processed = true; var spamReport = true; var unsubscribe = true; + var friendlyName = "My friendly name"; var apiResponse = @"{ ""enabled"": true, @@ -163,7 +164,8 @@ public async Task UpdateEventWebhookSettingsAsync() ""processed"": true, ""open"": true, ""click"": true, - ""dropped"": true + ""dropped"": true, + ""friendly_name"": ""My friendly name"" }"; var mockHttp = new MockHttpMessageHandler(); @@ -173,7 +175,7 @@ public async Task UpdateEventWebhookSettingsAsync() var webhooks = new WebhookSettings(client); // Act - var result = await webhooks.UpdateEventWebhookSettingsAsync(enabled, url, bounce, click, deferred, delivered, dropped, groupResubscribe, groupUnsubscribe, open, processed, spamReport, unsubscribe, null, CancellationToken.None); + var result = await webhooks.UpdateEventWebhookSettingsAsync(enabled, url, bounce, click, deferred, delivered, dropped, groupResubscribe, groupUnsubscribe, open, processed, spamReport, unsubscribe, friendlyName, null, null, null, null, CancellationToken.None); // Assert mockHttp.VerifyNoOutstandingExpectation(); @@ -194,7 +196,7 @@ public async Task SendEventTestAsync() var webhooks = new WebhookSettings(client); // Act - await webhooks.SendEventTestAsync(url, null, CancellationToken.None); + await webhooks.SendEventTestAsync(url, null, null, null, null, CancellationToken.None); // Assert mockHttp.VerifyNoOutstandingExpectation(); diff --git a/Source/StrongGrid/Extensions/Internal.cs b/Source/StrongGrid/Extensions/Internal.cs index b13c4a15..39eff042 100644 --- a/Source/StrongGrid/Extensions/Internal.cs +++ b/Source/StrongGrid/Extensions/Internal.cs @@ -870,6 +870,20 @@ internal static string ToExactLength(this string source, int totalWidth, string return result; } + internal static StrongGridJsonObject ToStrongGridJsonObject(this T source, bool ignoreDefault = true) + { + var jsonObject = new StrongGridJsonObject(); + foreach (var property in source.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)) + { + var propertyName = ((JsonPropertyNameAttribute)property.GetCustomAttribute(typeof(JsonPropertyNameAttribute))).Name; + var propertyValue = property.GetValue(source); + + jsonObject.AddProperty(propertyName, propertyValue, ignoreDefault); + } + + return jsonObject; + } + /// Asynchronously converts the JSON encoded content and convert it to an object of the desired type. /// The response model to deserialize into. /// The content. diff --git a/Source/StrongGrid/Extensions/Public.cs b/Source/StrongGrid/Extensions/Public.cs index 2a8415df..1d8443af 100644 --- a/Source/StrongGrid/Extensions/Public.cs +++ b/Source/StrongGrid/Extensions/Public.cs @@ -1539,5 +1539,116 @@ convert public keys when we stop suporting .NET framework and .NET standard. var webHookEvents = parser.ParseEventsWebhook(requestBody); return webHookEvents; } + + /// + /// Get the current event webhook settings. + /// + /// The webhook settings resource. + /// The user to impersonate. + /// The cancellation token. + /// + /// The . + /// + public static Task GetEventWebhookSettingsAsync(this IWebhookSettings webhookSettings, string onBehalfOf = null, CancellationToken cancellationToken = default) + { + return webhookSettings.GetEventWebhookSettingsAsync(null, onBehalfOf, cancellationToken); + } + + /// + /// Change the events settings. + /// + /// The webhook settings resource. + /// if set to true [enabled]. + /// The webhook endpoint url. + /// if set to true [bounce]. + /// if set to true [click]. + /// if set to true [deferred]. + /// if set to true [delivered]. + /// if set to true [dropped]. + /// if set to true [groupResubscribe]. + /// if set to true [groupUnsubscribe]. + /// if set to true [open]. + /// if set to true [processed]. + /// if set to true [spamReport]. + /// if set to true [unsubscribe]. + /// The friendly name. + /// The OAuth client ID that SendGrid will pass to your OAuth server or service provider to generate an OAuth access token. When passing data in this parameter, you must also specify the oauthTokenUrl. + /// The OAuth client secret that SendGrid will pass to your OAuth server or service provider to generate an OAuth access token. This secret is needed only once to create an access token. SendGrid will store the secret, allowing you to update your client ID and Token URL without passing the secret to SendGrid again. When passing data in this parameter, you must also specify the oauthClientId and oauthTokenUrl. + /// The URL where SendGrid will send the OAuth client ID and client secret to generate an OAuth access token. This should be your OAuth server or service provider. When passing data in this parameter, you must also specify the oauthClientId. + /// The user to impersonate. + /// The cancellation token. + /// + /// The . + /// + public static Task UpdateEventWebhookSettingsAsync( + this IWebhookSettings webhookSettings, + bool enabled, + string url, + bool bounce = default, + bool click = default, + bool deferred = default, + bool delivered = default, + bool dropped = default, + bool groupResubscribe = default, + bool groupUnsubscribe = default, + bool open = default, + bool processed = default, + bool spamReport = default, + bool unsubscribe = default, + string friendlyName = null, + string oauthClientId = null, + string oauthClientSecret = null, + string oAuthTokenUrl = null, + string onBehalfOf = null, + CancellationToken cancellationToken = default) + { + return webhookSettings.UpdateEventWebhookSettingsAsync(null, enabled, url, bounce, click, deferred, delivered, dropped, groupResubscribe, groupUnsubscribe, open, processed, spamReport, unsubscribe, friendlyName, oauthClientId, oauthClientSecret, oAuthTokenUrl, onBehalfOf, cancellationToken); + } + + /// + /// Sends a fake event notification post to the provided URL. + /// + /// The webhook settings resource. + /// The URL where you would like the test notification to be sent. + /// The client ID Twilio SendGrid sends to your OAuth server or service provider to generate an OAuth access token. When passing data in this parameter, you must also specify oauThokenUrl. + /// This value is needed only once to create an access token. SendGrid will store this secret, allowing you to update your Client ID and Token URL without passing the secret to SendGrid again. When passing data in this field, you must also specify oAuthClientId and oAuthTokenUrl. + /// The URL where Twilio SendGrid sends the Client ID and Client Secret to generate an access token. This should be your OAuth server or service provider. When passing data in this parameter, you must also include oAuthClientId. + /// The user to impersonate. + /// The cancellation token. + /// + /// The async task. + /// + public static Task SendEventTestAsync(this IWebhookSettings webhookSettings, string url, string oAuthClientId = null, string oAuthClientSecret = null, string oAuthTokenUrl = null, string onBehalfOf = null, CancellationToken cancellationToken = default) + { + return webhookSettings.SendEventTestAsync(null, url, oAuthClientId, oAuthClientSecret, oAuthTokenUrl, onBehalfOf, cancellationToken); + } + + /// + /// Enable or disable signature verification for a single Event Webhook. + /// + /// The webhook settings resource. + /// The ID of the Event Webhook you want to update. + /// Indicates if the signature verification should be enbladle or not. + /// The user to impersonate. + /// The cancellation token. + /// The async task. + public static Task ToggleEventWebhookSignatureVerificationAsync(this IWebhookSettings webhookSettings, string id, bool enabled, string onBehalfOf = null, CancellationToken cancellationToken = default) + { + return webhookSettings.ToggleEventWebhookSignatureVerificationAsync(null, enabled, onBehalfOf, cancellationToken); + } + + /// + /// Get the signed events public key. + /// + /// The webhook settings resource. + /// The user to impersonate. + /// The cancellation token. + /// + /// The public key. + /// + public static Task GetSignedEventsPublicKeyAsync(this IWebhookSettings webhookSettings, string onBehalfOf = null, CancellationToken cancellationToken = default) + { + return webhookSettings.GetSignedEventsPublicKeyAsync(null, onBehalfOf, cancellationToken); + } } } diff --git a/Source/StrongGrid/Models/EventWebhookSettings.cs b/Source/StrongGrid/Models/EventWebhookSettings.cs index 3156d162..52ddf7c4 100644 --- a/Source/StrongGrid/Models/EventWebhookSettings.cs +++ b/Source/StrongGrid/Models/EventWebhookSettings.cs @@ -1,3 +1,4 @@ +using System; using System.Text.Json.Serialization; namespace StrongGrid.Models @@ -8,44 +9,56 @@ namespace StrongGrid.Models public class EventWebhookSettings { /// - /// Gets or sets a value indicating whether this is enabled. + /// Gets or sets a value indicating whether the webhook is configured to send bounce events. /// + /// + /// A bounce occurs when a receiving server could not or would not accept a message. + /// /// /// true if enabled; otherwise, false. /// - [JsonPropertyName("enabled")] - public bool Enabled { get; set; } + [JsonPropertyName("bounce")] + public bool Bounce { get; set; } /// - /// Gets or sets the URL. + /// Gets or sets a value indicating whether the webhook is configured to send click events. /// + /// + /// Click events occur when a recipient clicks on a link within the message. You must enable Click Tracking to receive this type of event. + /// /// - /// The URL. + /// true if enabled; otherwise, false. /// - [JsonPropertyName("url")] - public string Url { get; set; } + [JsonPropertyName("click")] + public bool Click { get; set; } /// - /// Gets or sets a value indicating whether the ASM Group Resubscribe notification is sent. + /// Gets or sets the date this webhooks settings was created. /// /// - /// true if enabled; otherwise, false. + /// The created on. /// - [JsonPropertyName("group_resubscribe")] - public bool GroupResubscribe { get; set; } + [JsonPropertyName("created_date")] + public DateTime? CreatedOn { get; set; } /// - /// Gets or sets a value indicating whether the ASM Group Unsubscribe notification is sent. + /// Gets or sets a value indicating whether the the webhook is configured to send deferred events. /// + /// + /// Deferred events occur when a recipient's email server temporarily rejects a message. + /// /// /// true if enabled; otherwise, false. /// - [JsonPropertyName("group_unsubscribe")] - public bool GroupUnsubscribe { get; set; } + [JsonPropertyName("deferred")] + public bool Deferred { get; set; } /// - /// Gets or sets a value indicating whether the Delivered notification is sent. + /// Gets or sets a value indicating whether the Delivered notification is enabled. /// + /// + /// Delivered events occur when a message has been successfully delivered to the receiving server. + /// /// /// true if enabled; otherwise, false. /// @@ -53,44 +66,113 @@ public class EventWebhookSettings public bool Delivered { get; set; } /// - /// Gets or sets a value indicating whether the SpamReport notification is sent. + /// Gets or sets a value indicating whether the webhook is configured to send dropped events. /// + /// + /// Dropped events occur when your message is not delivered by Twilio SendGrid. + /// Dropped events are accomponied by a reason property, which indicates why the message was dropped. + /// Reasons for a dropped message include: + /// - Invalid SMTPAPI header, Spam Content (if spam checker app enabled) + /// - Unsubscribed Address + /// - Bounced Address + /// - Spam Reporting Address + /// - Invalid + /// - Recipient List over Package Quota. + /// /// /// true if enabled; otherwise, false. /// - [JsonPropertyName("spam_report")] - public bool SpamReport { get; set; } + [JsonPropertyName("dropped")] + public bool Dropped { get; set; } /// - /// Gets or sets a value indicating whether the Bounce notification is sent. + /// Gets or sets a value indicating whether this is enabled. /// /// /// true if enabled; otherwise, false. /// - [JsonPropertyName("bounce")] - public bool Bounce { get; set; } + [JsonPropertyName("enabled")] + public bool Enabled { get; set; } + + /// + /// Gets or sets an optional friendly name assigned to the Event Webhook to help you differentiate it. + /// + /// + /// The friendly name is for convenience only. + /// You should use the webhook id property for any programmatic tasks. + /// + [JsonPropertyName("friendly_name")] + public string FriendlyName { get; set; } /// - /// Gets or sets a value indicating whether the Deferred notification is sent. + /// Gets or sets a value indicating whether the webhook is configured to send group resubscribe events. /// + /// + /// Group resubscribes occur when recipients resubscribe to a specific unsubscribe group by updating their subscription preferences. + /// You must enable Subscription Tracking to receive this type of event. + /// /// /// true if enabled; otherwise, false. /// - [JsonPropertyName("deferred")] - public bool Deferred { get; set; } + [JsonPropertyName("group_resubscribe")] + public bool GroupResubscribe { get; set; } /// - /// Gets or sets a value indicating whether the Unsubscribe notification is sent. + /// Gets or sets a value indicating whether the webhook is configured to send group unsubscribe events. /// + /// + /// Group unsubscribes occur when recipients unsubscribe from a specific unsubscribe group either by direct link or by updating their subscription preferences. + /// You must enable Subscription Tracking to receive this type of event. + /// /// /// true if enabled; otherwise, false. /// - [JsonPropertyName("unsubscribe")] - public bool Unsubscribe { get; set; } + [JsonPropertyName("group_unsubscribe")] + public bool GroupUnsubscribe { get; set; } /// - /// Gets or sets a value indicating whether the Processed notification is sent. + /// Gets or sets a unique string used to identify the webhook. /// + /// + /// A webhook's ID is generated programmatically and cannot be changed after creation. + /// You can assign a natural language identifier to your webhook using the property. + /// + [JsonPropertyName("id")] + public string Id { get; set; } + + /// + /// Gets or sets the OAuth client ID SendGrid sends to your OAuth server or service provider to generate an OAuth access token. + /// + [JsonPropertyName("oauth_client_id")] + public string OauthClientId { get; set; } + + /// + /// Gets or sets the ThURL where SendGrid sends the OAuth client ID and client secret to generate an access token. + /// + /// + /// This should be your OAuth server or service provider. + /// + [JsonPropertyName("oauth_token_url")] + public string OauthTokenUrl { get; set; } + + /// + /// Gets or sets a value indicating whether the webhook is configured to send open events. + /// + /// + /// Open events occur when a recipient has opened the HTML message.You must enable Open Tracking to receive this type of event. + /// + /// + /// true if enabled; otherwise, false. + /// + [JsonPropertyName("open")] + public bool Open { get; set; } + + /// + /// Gets or sets a value indicating whether the webhook is configured to send processed events. + /// + /// + /// Processed events occur when a message has been received by Twilio SendGrid and is ready to be delivered. + /// /// /// true if enabled; otherwise, false. /// @@ -98,30 +180,52 @@ public class EventWebhookSettings public bool Processed { get; set; } /// - /// Gets or sets a value indicating whether the Open notification is sent. + /// Gets or sets the public key which can be used to verify the SendGrid signature. + /// + [JsonPropertyName("public_key")] + public string PublicKey { get; set; } + + /// + /// Gets or sets a value indicating whether the webhook is configured to send spam report events. /// + /// + /// Spam reports occur when recipients mark a message as spam. + /// /// /// true if enabled; otherwise, false. /// - [JsonPropertyName("open")] - public bool Open { get; set; } + [JsonPropertyName("spam_report")] + public bool SpamReport { get; set; } /// - /// Gets or sets a value indicating whether the Click notification is sent. + /// Gets or sets a value indicating whether the webhook is configured to send unsubscribe events. /// + /// + /// Unsubscribes occur when recipients click on a message's subscription management link. + /// You must enable Subscription Tracking to receive this type of event. + /// /// /// true if enabled; otherwise, false. /// - [JsonPropertyName("click")] - public bool Click { get; set; } + [JsonPropertyName("unsubscribe")] + public bool Unsubscribe { get; set; } /// - /// Gets or sets a value indicating whether the Dropped notification is sent. + /// Gets or sets the date this webhooks settings was updated. /// /// - /// true if enabled; otherwise, false. + /// The created on. /// - [JsonPropertyName("dropped")] - public bool Dropped { get; set; } + [JsonPropertyName("updated_date")] + public DateTime? UpdatedOn { get; set; } + + /// + /// Gets or sets the URL where SendGrid will send event data. + /// + /// + /// The URL. + /// + [JsonPropertyName("url")] + public string Url { get; set; } } } diff --git a/Source/StrongGrid/Resources/IWebhookSettings.cs b/Source/StrongGrid/Resources/IWebhookSettings.cs index eba36027..62a0e293 100644 --- a/Source/StrongGrid/Resources/IWebhookSettings.cs +++ b/Source/StrongGrid/Resources/IWebhookSettings.cs @@ -16,20 +16,78 @@ namespace StrongGrid.Resources public interface IWebhookSettings { /// - /// Get the current events settings. + /// Retrieve a single Event Webhook by ID. /// + /// The ID of the Event Webhook you want to retrieve. /// The user to impersonate. /// The cancellation token. /// /// The . /// - Task GetEventWebhookSettingsAsync(string onBehalfOf = null, CancellationToken cancellationToken = default); + Task GetEventWebhookSettingsAsync(string id, string onBehalfOf = null, CancellationToken cancellationToken = default); + + /// + /// Get all the event webhook settings. + /// + /// The user to impersonate. + /// The cancellation token. + /// + /// An array of . + /// + Task GetAllEventWebhookSettingsAsync(string onBehalfOf = null, CancellationToken cancellationToken = default); + + /// + /// Create event webhook settings. + /// + /// if set to true [enabled]. + /// The webhook endpoint url. + /// if set to true [bounce]. + /// if set to true [click]. + /// if set to true [deferred]. + /// if set to true [delivered]. + /// if set to true [dropped]. + /// if set to true [groupResubscribe]. + /// if set to true [groupUnsubscribe]. + /// if set to true [open]. + /// if set to true [processed]. + /// if set to true [spamReport]. + /// if set to true [unsubscribe]. + /// The friendly name. + /// The OAuth client ID that SendGrid will pass to your OAuth server or service provider to generate an OAuth access token. When passing data in this parameter, you must also specify the oAuthTokenUrl. + /// The OAuth client secret that SendGrid will pass to your OAuth server or service provider to generate an OAuth access token. This secret is needed only once to create an access token. SendGrid will store the secret, allowing you to update your client ID and Token URL without passing the secret to SendGrid again. When passing data in this parameter, you must also specify the oAuthClientId and oAuthTokenUrl. + /// The URL where SendGrid will send the OAuth client ID and client secret to generate an OAuth access token. This should be your OAuth server or service provider. When passing data in this parameter, you must also specify the oAuthClientId. + /// The user to impersonate. + /// The cancellation token. + /// + /// The . + /// + Task CreateEventWebhookSettingsAsync( + bool enabled, + string url, + bool bounce = default, + bool click = default, + bool deferred = default, + bool delivered = default, + bool dropped = default, + bool groupResubscribe = default, + bool groupUnsubscribe = default, + bool open = default, + bool processed = default, + bool spamReport = default, + bool unsubscribe = default, + string friendlyName = null, + string oAuthClientId = null, + string oAuthClientSecret = null, + string oAuthTokenUrl = null, + string onBehalfOf = null, + CancellationToken cancellationToken = default); /// /// Change the events settings. /// + /// The ID of the Event Webhook you want to update. /// if set to true [enabled]. - /// the webhook endpoint url. + /// The webhook endpoint url. /// if set to true [bounce]. /// if set to true [click]. /// if set to true [deferred]. @@ -41,12 +99,17 @@ public interface IWebhookSettings /// if set to true [processed]. /// if set to true [spamReport]. /// if set to true [unsubscribe]. + /// The friendly name. + /// The OAuth client ID that SendGrid will pass to your OAuth server or service provider to generate an OAuth access token. When passing data in this parameter, you must also specify the oAuthTokenUrl. + /// The OAuth client secret that SendGrid will pass to your OAuth server or service provider to generate an OAuth access token. This secret is needed only once to create an access token. SendGrid will store the secret, allowing you to update your client ID and Token URL without passing the secret to SendGrid again. When passing data in this parameter, you must also specify the oAuthClientId and oAuthTokenUrl. + /// The URL where SendGrid will send the OAuth client ID and client secret to generate an OAuth access token. This should be your OAuth server or service provider. When passing data in this parameter, you must also specify the oAuthClientId. /// The user to impersonate. /// The cancellation token. /// /// The . /// Task UpdateEventWebhookSettingsAsync( + string id, bool enabled, string url, bool bounce = default, @@ -60,19 +123,37 @@ Task UpdateEventWebhookSettingsAsync( bool processed = default, bool spamReport = default, bool unsubscribe = default, + string friendlyName = null, + string oAuthClientId = null, + string oAuthClientSecret = null, + string oAuthTokenUrl = null, string onBehalfOf = null, CancellationToken cancellationToken = default); + /// + /// Enable or disable signature verification for a single Event Webhook. + /// + /// The ID of the Event Webhook you want to update. + /// Indicates if the signature verification should be enbladle or not. + /// The user to impersonate. + /// The cancellation token. + /// The async task. + Task ToggleEventWebhookSignatureVerificationAsync(string id, bool enabled, string onBehalfOf = null, CancellationToken cancellationToken = default); + /// /// Sends a fake event notification post to the provided URL. /// - /// the event notification endpoint url. + /// The ID of the Event Webhook you want to retrieve. + /// The URL where you would like the test notification to be sent. + /// The client ID Twilio SendGrid sends to your OAuth server or service provider to generate an OAuth access token. When passing data in this parameter, you must also specify oauThokenUrl. + /// This value is needed only once to create an access token. SendGrid will store this secret, allowing you to update your Client ID and Token URL without passing the secret to SendGrid again. When passing data in this field, you must also specify oAuthClientId and oAuthTokenUrl. + /// The URL where Twilio SendGrid sends the Client ID and Client Secret to generate an access token. This should be your OAuth server or service provider. When passing data in this parameter, you must also include oAuthClientId. /// The user to impersonate. /// The cancellation token. /// /// The async task. /// - Task SendEventTestAsync(string url, string onBehalfOf = null, CancellationToken cancellationToken = default); + Task SendEventTestAsync(string id, string url, string oAuthClientId = null, string oAuthClientSecret = null, string oAuthTokenUrl = null, string onBehalfOf = null, CancellationToken cancellationToken = default); /// /// Create inbound parse settings for a hostname. @@ -94,7 +175,7 @@ Task UpdateEventWebhookSettingsAsync( /// The user to impersonate. /// The cancellation token. /// - /// The . + /// An array of . /// Task GetAllInboundParseWebhookSettingsAsync(string onBehalfOf = null, CancellationToken cancellationToken = default); @@ -137,10 +218,23 @@ Task UpdateEventWebhookSettingsAsync( /// /// Get the signed events public key. /// + /// The ID of the Event Webhook you want to retrieve. + /// The user to impersonate. /// The cancellation token. /// /// The public key. /// - Task GetSignedEventsPublicKeyAsync(CancellationToken cancellationToken = default); + Task GetSignedEventsPublicKeyAsync(string id, string onBehalfOf = null, CancellationToken cancellationToken = default); + + /// + /// Delete a single Event Webhook by ID. + /// + /// The ID of the Event Webhook you want to delete. + /// The user to impersonate. + /// The cancellation token. + /// + /// The async task. + /// + Task DeleteEventWebhookSettingsAsync(string id, string onBehalfOf = null, CancellationToken cancellationToken = default); } } diff --git a/Source/StrongGrid/Resources/WebhookSettings.cs b/Source/StrongGrid/Resources/WebhookSettings.cs index 821e8ec0..db73119c 100644 --- a/Source/StrongGrid/Resources/WebhookSettings.cs +++ b/Source/StrongGrid/Resources/WebhookSettings.cs @@ -32,45 +32,89 @@ internal WebhookSettings(Pathoschild.Http.Client.IClient client) _client = client; } - /// - /// Get the current event webhook settings. - /// - /// The user to impersonate. - /// The cancellation token. - /// - /// The . - /// - public Task GetEventWebhookSettingsAsync(string onBehalfOf = null, CancellationToken cancellationToken = default) + /// + public Task GetEventWebhookSettingsAsync(string id, string onBehalfOf = null, CancellationToken cancellationToken = default) { + var endpointUrl = $"{_eventWebhookEndpoint}/settings"; + if (!string.IsNullOrEmpty(id)) endpointUrl += $"/{id}"; + return _client - .GetAsync($"{_eventWebhookEndpoint}/settings") + .GetAsync(endpointUrl) .OnBehalfOf(onBehalfOf) .WithCancellationToken(cancellationToken) .AsObject(); } - /// - /// Change the event webhook settings. - /// - /// if set to true [enabled]. - /// the webhook endpoint url. - /// if set to true [bounce]. - /// if set to true [click]. - /// if set to true [deferred]. - /// if set to true [delivered]. - /// if set to true [dropped]. - /// if set to true [groupResubscribe]. - /// if set to true [groupUnsubscribe]. - /// if set to true [open]. - /// if set to true [processed]. - /// if set to true [spamReport]. - /// if set to true [unsubscribe]. - /// The user to impersonate. - /// The cancellation token. - /// - /// The . - /// + /// + public Task GetAllEventWebhookSettingsAsync(string onBehalfOf = null, CancellationToken cancellationToken = default) + { + return _client + .GetAsync($"{_eventWebhookEndpoint}/settings/all") + .OnBehalfOf(onBehalfOf) + .WithCancellationToken(cancellationToken) + .AsObject("webhooks"); + } + + /// + public Task CreateEventWebhookSettingsAsync( + bool enabled, + string url, + bool bounce = default, + bool click = default, + bool deferred = default, + bool delivered = default, + bool dropped = default, + bool groupResubscribe = default, + bool groupUnsubscribe = default, + bool open = default, + bool processed = default, + bool spamReport = default, + bool unsubscribe = default, + string friendlyName = null, + string oAuthClientId = null, + string oAuthClientSecret = null, + string oAuthTokenUrl = null, + string onBehalfOf = null, + CancellationToken cancellationToken = default) + { + if (string.IsNullOrEmpty(url)) throw new ArgumentNullException(nameof(url)); + + var endpointUrl = $"{_eventWebhookEndpoint}/settings"; + + var eventWebhookSettings = new EventWebhookSettings + { + Enabled = enabled, + Url = url, + Bounce = bounce, + Click = click, + Deferred = deferred, + Delivered = delivered, + Dropped = dropped, + FriendlyName = friendlyName, + GroupResubscribe = groupResubscribe, + GroupUnsubscribe = groupUnsubscribe, + Open = open, + Processed = processed, + SpamReport = spamReport, + Unsubscribe = unsubscribe, + OauthClientId = oAuthClientId, + OauthTokenUrl = oAuthTokenUrl, + }; + + var jsonObject = eventWebhookSettings.ToStrongGridJsonObject(); + jsonObject.AddProperty("oauth_client_secret", oAuthClientSecret); + + return _client + .PostAsync(endpointUrl) + .OnBehalfOf(onBehalfOf) + .WithJsonBody(jsonObject) + .WithCancellationToken(cancellationToken) + .AsObject(); + } + + /// public Task UpdateEventWebhookSettingsAsync( + string id, bool enabled, string url, bool bounce = default, @@ -84,13 +128,21 @@ public Task UpdateEventWebhookSettingsAsync( bool processed = default, bool spamReport = default, bool unsubscribe = default, + string friendlyName = null, + string oAuthClientId = null, + string oAuthClientSecret = null, + string oAuthTokenUrl = null, string onBehalfOf = null, CancellationToken cancellationToken = default) { if (string.IsNullOrEmpty(url)) throw new ArgumentNullException(nameof(url)); + var endpointUrl = $"{_eventWebhookEndpoint}/settings"; + if (!string.IsNullOrEmpty(id)) endpointUrl += $"/{id}"; + var eventWebhookSettings = new EventWebhookSettings { + Id = id, Enabled = enabled, Url = url, Bounce = bounce, @@ -98,37 +150,56 @@ public Task UpdateEventWebhookSettingsAsync( Deferred = deferred, Delivered = delivered, Dropped = dropped, + FriendlyName = friendlyName, GroupResubscribe = groupResubscribe, GroupUnsubscribe = groupUnsubscribe, Open = open, Processed = processed, SpamReport = spamReport, - Unsubscribe = unsubscribe + Unsubscribe = unsubscribe, + OauthClientId = oAuthClientId, + OauthTokenUrl = oAuthTokenUrl, }; + var jsonObject = eventWebhookSettings.ToStrongGridJsonObject(); + jsonObject.AddProperty("oauth_client_secret", oAuthClientSecret); + return _client - .PatchAsync($"{_eventWebhookEndpoint}/settings") + .PatchAsync(endpointUrl) .OnBehalfOf(onBehalfOf) - .WithJsonBody(eventWebhookSettings) + .WithJsonBody(jsonObject) .WithCancellationToken(cancellationToken) .AsObject(); } - /// - /// Sends a fake event notification post to the provided URL. - /// - /// the event notification endpoint url. - /// The user to impersonate. - /// The cancellation token. - /// - /// The async task. - /// - public Task SendEventTestAsync(string url, string onBehalfOf = null, CancellationToken cancellationToken = default) + /// + public Task ToggleEventWebhookSignatureVerificationAsync(string id, bool enabled, string onBehalfOf = null, CancellationToken cancellationToken = default) + { + var endpointUrl = $"{_eventWebhookEndpoint}/settings/signed"; + if (!string.IsNullOrEmpty(id)) endpointUrl += $"/{id}"; + + var data = new StrongGridJsonObject(); + data.AddProperty("enabled", enabled); + + return _client + .PatchAsync(endpointUrl) + .OnBehalfOf(onBehalfOf) + .WithJsonBody(data) + .WithCancellationToken(cancellationToken) + .AsMessage(); + } + + /// + public Task SendEventTestAsync(string id, string url, string oAuthClientId = null, string oAuthClientSecret = null, string oAuthTokenUrl = null, string onBehalfOf = null, CancellationToken cancellationToken = default) { if (string.IsNullOrEmpty(url)) throw new ArgumentNullException(nameof(url)); var data = new StrongGridJsonObject(); + data.AddProperty("id", id); data.AddProperty("url", url); + data.AddProperty("oauth_client_id", oAuthClientId); + data.AddProperty("oauth_client_secret", oAuthClientSecret); + data.AddProperty("oauth_token_url", oAuthTokenUrl); return _client .PostAsync($"{_eventWebhookEndpoint}/test") @@ -155,7 +226,7 @@ public Task CreateInboundParseWebhookSettingsAsync( if (string.IsNullOrEmpty(hostname)) throw new ArgumentNullException(nameof(hostname)); if (string.IsNullOrEmpty(url)) throw new ArgumentNullException(nameof(url)); - var data = ConvertToJson(hostname, url, spamCheck, sendRaw); + var data = ConvertInboundParseSettingsToJson(hostname, url, spamCheck, sendRaw); return _client .PostAsync($"{_inboundParseWebhookEndpoint}/settings") .OnBehalfOf(onBehalfOf) @@ -217,7 +288,7 @@ public Task UpdateInboundParseWebhookSettingsAsync(string hostname, Parameter - /// Get the signed events public key. - /// - /// The cancellation token. - /// - /// The public key. - /// - public Task GetSignedEventsPublicKeyAsync(CancellationToken cancellationToken = default) + /// + public Task GetSignedEventsPublicKeyAsync(string id, string onBehalfOf = null, CancellationToken cancellationToken = default) { + var endpointUrl = $"{_eventWebhookEndpoint}/settings/signed"; + if (!string.IsNullOrEmpty(id)) endpointUrl += $"/{id}"; + return _client - .GetAsync($"{_eventWebhookEndpoint}/settings/signed") + .GetAsync(endpointUrl) + .OnBehalfOf(onBehalfOf) .WithCancellationToken(cancellationToken) .AsObject("public_key"); } - private static StrongGridJsonObject ConvertToJson(string hostname, Parameter url, Parameter spamCheck, Parameter sendRaw) + /// + public Task DeleteEventWebhookSettingsAsync(string id, string onBehalfOf = null, CancellationToken cancellationToken = default) + { + if (string.IsNullOrEmpty(id)) throw new ArgumentNullException(nameof(id)); + + return _client + .DeleteAsync($"{_eventWebhookEndpoint}/settings/{id}") + .OnBehalfOf(onBehalfOf) + .WithCancellationToken(cancellationToken) + .AsMessage(); + } + + private static StrongGridJsonObject ConvertInboundParseSettingsToJson(string hostname, Parameter url, Parameter spamCheck, Parameter sendRaw) { var result = new StrongGridJsonObject(); result.AddProperty("hostname", hostname);