From f3d20f8c76b995bc19c27b792f4865f57a5c8244 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Fri, 19 Jan 2018 08:29:44 -0800 Subject: [PATCH] Remove ASP.NET Core WebHooks code and infrastructure - part of aspnet/WebHooks#228 - all deletions except removing content of root Directory.Build.* files - leave WebHooks.sln because it's used in `GetDirectoryNameOfFileAbove(...)` --- Directory.Build.props | 62 +- Directory.Build.targets | 27 +- global.json | 5 - .../AzureAlertCoreReceiver.csproj | 12 - .../Controllers/AzureAlertController.cs | 48 -- samples/AzureAlertCoreReceiver/Program.cs | 18 - samples/AzureAlertCoreReceiver/Startup.cs | 29 - .../BitbucketCoreReceiver.csproj | 12 - .../Controllers/BitbucketController.cs | 82 --- samples/BitbucketCoreReceiver/Program.cs | 18 - samples/BitbucketCoreReceiver/Startup.cs | 29 - .../BitbucketCoreReceiver/appsettings.json | 15 - .../BitbucketChange.cs | 25 - .../BitbucketCommit.cs | 24 - .../BitbucketPush.cs | 16 - .../BitbucketPushNotification.cs | 20 - .../BitbucketState.cs | 21 - .../BitbucketStronglyTypedCoreReceiver.csproj | 12 - .../Controllers/BitbucketController.cs | 82 --- .../Program.cs | 18 - .../Startup.cs | 29 - .../appsettings.json | 15 - samples/Directory.Build.props | 12 - .../Controllers/DropboxController.cs | 31 - .../DropboxCoreReceiver.csproj | 12 - samples/DropboxCoreReceiver/Program.cs | 18 - samples/DropboxCoreReceiver/Startup.cs | 29 - .../Controllers/DynamicsCRMController.cs | 53 -- .../DynamicsCRMCoreReceiver.csproj | 12 - samples/DynamicsCRMCoreReceiver/Program.cs | 18 - samples/DynamicsCRMCoreReceiver/Startup.cs | 29 - .../DynamicsCRMCoreReceiver/appsettings.json | 15 - .../Controllers/GitHubController.cs | 64 --- .../GitHubCoreReceiver.csproj | 12 - samples/GitHubCoreReceiver/Program.cs | 18 - samples/GitHubCoreReceiver/Startup.cs | 29 - .../Controllers/KuduController.cs | 42 -- .../KuduCoreReceiver/KuduCoreReceiver.csproj | 12 - samples/KuduCoreReceiver/Program.cs | 18 - samples/KuduCoreReceiver/Startup.cs | 29 - .../Controllers/MailChimpController.cs | 31 - .../MailChimpCoreReceiver.csproj | 12 - samples/MailChimpCoreReceiver/Program.cs | 18 - samples/MailChimpCoreReceiver/Startup.cs | 29 - .../Controllers/PusherController.cs | 164 ------ samples/PusherCoreReceiver/Program.cs | 18 - .../PusherCoreReceiver.csproj | 19 - samples/PusherCoreReceiver/Startup.cs | 32 -- samples/PusherCoreReceiver/appsettings.json | 15 - samples/PusherCoreReceiver/wwwroot/index.html | 25 - .../Controllers/SalesforceController.cs | 74 --- samples/SalesforceCoreReceiver/Program.cs | 18 - .../SalesforceCoreReceiver.csproj | 12 - samples/SalesforceCoreReceiver/Startup.cs | 29 - .../SalesforceCoreReceiver/appsettings.json | 15 - .../Controllers/SlackController.cs | 163 ------ samples/SlackCoreReceiver/Program.cs | 18 - .../SlackCoreReceiver.csproj | 12 - samples/SlackCoreReceiver/Startup.cs | 29 - samples/SlackCoreReceiver/appsettings.json | 15 - .../Controllers/StripeController.cs | 72 --- samples/StripeCoreReceiver/Program.cs | 18 - samples/StripeCoreReceiver/Startup.cs | 24 - .../StripeCoreReceiver.csproj | 12 - samples/StripeCoreReceiver/appsettings.json | 15 - src/Directory.Build.props | 22 - .../AzureAlertCondition.cs | 73 --- .../AzureAlertConstants.cs | 22 - .../AzureAlertContext.cs | 94 --- .../AzureAlertNotification.cs | 38 -- .../AzureAlertWebHookAttribute.cs | 51 -- .../AzureAlertMvcBuilderExtensions.cs | 44 -- .../AzureAlertMvcCoreBuilderExtensions.cs | 46 -- .../AzureAlertServiceCollectionSetup.cs | 30 - .../Metadata/AzureAlertMetadata.cs | 36 -- ...tCore.WebHooks.Receivers.AzureAlert.csproj | 12 - .../BitbucketAuthor.cs | 25 - .../BitbucketConstants.cs | 37 -- .../BitbucketLink.cs | 19 - .../BitbucketParent.cs | 38 -- .../BitbucketRepository.cs | 67 --- .../BitbucketTarget.cs | 68 --- .../BitbucketUser.cs | 50 -- .../BitbucketWebHookAttribute.cs | 77 --- .../BitbucketMvcBuilderExtensions.cs | 43 -- .../BitbucketMvcCoreBuilderExtensions.cs | 45 -- .../BitbucketServiceCollectionSetup.cs | 30 - .../Metadata/BitbucketMetadata.cs | 59 -- ...etCore.WebHooks.Receivers.BitBucket.csproj | 12 - .../Properties/Resources.Designer.cs | 72 --- .../Properties/Resources.resx | 123 ---- .../DropboxConstants.cs | 44 -- .../DropboxWebHookAttribute.cs | 49 -- .../Extensions/DropboxMvcBuilderExtensions.cs | 43 -- .../DropboxMvcCoreBuilderExtensions.cs | 45 -- .../Filters/DropboxVerifySignatureFilter.cs | 119 ---- .../Internal/DropboxServiceCollectionSetup.cs | 50 -- .../Metadata/DropboxMetadata.cs | 50 -- ...pNetCore.WebHooks.Receivers.Dropbox.csproj | 12 - .../DynamicsCRMConstants.cs | 22 - .../DynamicsCRMWebHookAttribute.cs | 50 -- .../DynamicsCRMMvcBuilderExtensions.cs | 44 -- .../DynamicsCRMMvcCoreBuilderExtensions.cs | 46 -- .../DynamicsCRMServiceCollectionSetup.cs | 30 - .../Metadata/DynamicsCRMMetadata.cs | 36 -- ...Core.WebHooks.Receivers.DynamicsCRM.csproj | 12 - .../Extensions/GitHubMvcBuilderExtensions.cs | 42 -- .../GitHubMvcCoreBuilderExtensions.cs | 44 -- .../Filters/GitHubVerifySignatureFilter.cs | 157 ----- .../GitHubConstants.cs | 47 -- .../GitHubWebHookAttribute.cs | 86 --- .../Internal/GitHubServiceCollectionSetup.cs | 50 -- .../Metadata/GitHubMetadata.cs | 35 -- ...spNetCore.WebHooks.Receivers.GitHub.csproj | 15 - .../Properties/AssemblyInfo.cs | 6 - .../Properties/Resources.Designer.cs | 81 --- .../Properties/Resources.resx | 126 ---- .../Extensions/KuduMvcBuilderExtensions.cs | 43 -- .../KuduMvcCoreBuilderExtensions.cs | 45 -- .../Internal/KuduServiceCollectionSetup.cs | 30 - .../KuduConstants.cs | 21 - .../KuduNotification.cs | 98 ---- .../KuduWebHookAttribute.cs | 50 -- .../Metadata/KuduMetadata.cs | 36 -- ....AspNetCore.WebHooks.Receivers.Kudu.csproj | 12 - .../MailChimpMvcBuilderExtensions.cs | 43 -- .../MailChimpMvcCoreBuilderExtensions.cs | 43 -- .../MailChimpServiceCollectionSetup.cs | 30 - .../MailChimpConstants.cs | 22 - .../MailChimpWebHookAttribute.cs | 50 -- .../Metadata/MailChimpMetadata.cs | 48 -- ...etCore.WebHooks.Receivers.MailChimp.csproj | 11 - .../Extensions/PusherMvcBuilderExtensions.cs | 43 -- .../PusherMvcCoreBuilderExtensions.cs | 45 -- .../Filters/PusherVerifySignatureFilter.cs | 147 ----- .../Internal/PusherServiceCollectionSetup.cs | 50 -- .../Metadata/PusherMetadata.cs | 32 -- ...spNetCore.WebHooks.Receivers.Pusher.csproj | 12 - .../Properties/Resources.Designer.cs | 72 --- .../Properties/Resources.resx | 123 ---- .../PusherConstants.cs | 67 --- .../PusherNotifications.cs | 41 -- .../PusherWebHookAttribute.cs | 48 -- .../SalesforceMvcBuilderExtensions.cs | 47 -- .../SalesforceMvcCoreBuilderExtensions.cs | 47 -- .../SalesforceVerifyOrganizationIdFilter.cs | 201 ------- .../ISalesforceResultCreator.cs | 35 -- .../Internal/SalesforceResultCreator.cs | 105 ---- .../SalesforceServiceCollectionSetup.cs | 67 --- .../Messages/FaultResponse.xml | 10 - .../Messages/NotificationResponse.xml | 8 - .../Metadata/SalesforceMetadata.cs | 22 - ...tCore.WebHooks.Receivers.Salesforce.csproj | 16 - .../SalesforceNotificationsModelBinder.cs | 62 -- ...esforceNotificationsModelBinderProvider.cs | 50 -- .../Properties/Resources.Designer.cs | 90 --- .../Properties/Resources.resx | 129 ----- .../SalesforceConstants.cs | 39 -- .../SalesforceNamespaces.cs | 38 -- .../SalesforceNotifications.cs | 201 ------- .../SalesforceWebHookAttribute.cs | 50 -- .../Extensions/SlackMvcBuilderExtensions.cs | 43 -- .../SlackMvcCoreBuilderExtensions.cs | 46 -- .../Filters/SlackVerifyTokenFilter.cs | 213 ------- .../Internal/SlackServiceCollectionSetup.cs | 50 -- .../Metadata/SlackMetadata.cs | 38 -- ...AspNetCore.WebHooks.Receivers.Slack.csproj | 15 - .../Properties/Resources.Designer.cs | 126 ---- .../Properties/Resources.resx | 141 ----- .../SlackAttachment.cs | 168 ------ .../SlackCommand.cs | 393 ------------- .../SlackConstants.cs | 73 --- .../SlackField.cs | 96 ---- .../SlackResponse.cs | 50 -- .../SlackSlashResponse.cs | 112 ---- .../SlackWebHookAttribute.cs | 79 --- .../Extensions/StripeMvcBuilderExtensions.cs | 46 -- .../StripeMvcCoreBuilderExtensions.cs | 48 -- .../Filters/StripeTestEventRequestFilter.cs | 101 ---- .../StripeVerifyNotificationIdFilter.cs | 142 ----- .../Filters/StripeVerifySignatureFilter.cs | 265 --------- .../Internal/StripeServiceCollectionSetup.cs | 55 -- .../Metadata/StripeMetadata.cs | 38 -- ...spNetCore.WebHooks.Receivers.Stripe.csproj | 15 - .../ModelBinding/UnixTimeConverter.cs | 112 ---- .../Properties/Resources.Designer.cs | 108 ---- .../Properties/Resources.resx | 135 ----- .../StripeConstants.cs | 118 ---- .../StripeEvent.cs | 81 --- .../StripeEventData.cs | 31 - .../StripeRequestData.cs | 28 - .../StripeWebHookAttribute.cs | 51 -- ...spNetCore.WebHooks.Receivers.Trello.csproj | 11 - ...etCore.WebHooks.Receivers.WordPress.csproj | 11 - .../WebHookMetadataProvider.cs | 411 ------------- .../WebHookModelBindingProvider.cs | 237 -------- .../WebHookRoutingProvider.cs | 209 ------- .../Extensions/WebHookMvcBuilderExtensions.cs | 42 -- .../WebHookMvcCoreBuilderExtensions.cs | 42 -- .../Extensions/WebHookRouteDataExtensions.cs | 202 ------- .../Filters/WebHookEventMapperFilter.cs | 221 ------- .../Filters/WebHookGetRequestFilter.cs | 158 ----- .../Filters/WebHookPingRequestFilter.cs | 95 --- .../Filters/WebHookReceiverExistsFilter.cs | 156 ----- .../Filters/WebHookSecurityFilter.cs | 354 ------------ .../Filters/WebHookVerifyBodyTypeFilter.cs | 215 ------- .../Filters/WebHookVerifyCodeFilter.cs | 171 ------ .../Filters/WebHookVerifyMethodFilter.cs | 115 ---- .../WebHookVerifyRequiredValueFilter.cs | 223 ------- .../Filters/WebHookVerifySignatureFilter.cs | 349 ----------- .../GeneralWebHookAttribute.cs | 101 ---- .../IWebHookReceiver.cs | 36 -- .../IWebHookRequestReader.cs | 38 -- .../Internal/WebHookRequestReader.cs | 138 ----- .../Internal/WebHookServiceCollectionSetup.cs | 82 --- .../Metadata/IWebHookBindingMetadata.cs | 33 -- .../Metadata/IWebHookBodyTypeMetadata.cs | 25 - .../IWebHookBodyTypeMetadataService.cs | 14 - .../Metadata/IWebHookEventFromBodyMetadata.cs | 42 -- .../Metadata/IWebHookEventMetadata.cs | 42 -- .../Metadata/IWebHookEventSelectorMetadata.cs | 28 - .../Metadata/IWebHookGetRequestMetadata.cs | 48 -- .../Metadata/IWebHookMetadata.cs | 14 - .../Metadata/IWebHookPingRequestMetadata.cs | 25 - .../Metadata/IWebHookVerifyCodeMetadata.cs | 21 - .../Metadata/WebHookBodyType.cs | 30 - .../Metadata/WebHookMetadata.cs | 47 -- .../Metadata/WebHookParameter.cs | 90 --- .../Metadata/WebHookParameterType.cs | 32 -- ...osoft.AspNetCore.WebHooks.Receivers.csproj | 15 - .../Properties/AssemblyInfo.cs | 6 - .../Properties/Resources.Designer.cs | 333 ----------- .../Properties/Resources.resx | 210 ------- .../Routing/WebHookEventMapperConstraint.cs | 164 ------ .../Routing/WebHookEventNamesConstraint.cs | 106 ---- .../Routing/WebHookIdConstraint.cs | 57 -- .../WebHookMultipleEventNamesConstraint.cs | 70 --- .../WebHookReceiverExistsConstraint.cs | 63 -- .../Routing/WebHookReceiverNameConstraint.cs | 59 -- .../WebHookSingleEventNamesConstraint.cs | 50 -- .../Utilities/WebHookHttpRequestUtilities.cs | 45 -- .../WebHookAttribute.cs | 101 ---- .../WebHookConstants.cs | 109 ---- src/shared/Utilities/ObjectPathUtilities.cs | 81 --- src/shared/Utilities/TrimmingTokenizer.cs | 202 ------- test/Directory.Build.props | 15 - ...tCore.WebHooks.Receivers.Slack.Test.csproj | 15 - .../SlackCommandTests.cs | 293 ---------- .../StripeVerifySignatureFilterTests.cs | 542 ------------------ ...Core.WebHooks.Receivers.Stripe.Test.csproj | 16 - .../ModelBinding/UnixTimeConverterTests.cs | 156 ----- .../Internal/TrimmingTokenizerTests.cs | 272 --------- ...oft.AspNetCore.WebHooks.shared.Test.csproj | 18 - tools/Directory.Build.props | 7 - 254 files changed, 3 insertions(+), 17141 deletions(-) delete mode 100644 global.json delete mode 100644 samples/AzureAlertCoreReceiver/AzureAlertCoreReceiver.csproj delete mode 100644 samples/AzureAlertCoreReceiver/Controllers/AzureAlertController.cs delete mode 100644 samples/AzureAlertCoreReceiver/Program.cs delete mode 100644 samples/AzureAlertCoreReceiver/Startup.cs delete mode 100644 samples/BitbucketCoreReceiver/BitbucketCoreReceiver.csproj delete mode 100644 samples/BitbucketCoreReceiver/Controllers/BitbucketController.cs delete mode 100644 samples/BitbucketCoreReceiver/Program.cs delete mode 100644 samples/BitbucketCoreReceiver/Startup.cs delete mode 100644 samples/BitbucketCoreReceiver/appsettings.json delete mode 100644 samples/BitbucketStronglyTypedCoreReceiver/BitbucketChange.cs delete mode 100644 samples/BitbucketStronglyTypedCoreReceiver/BitbucketCommit.cs delete mode 100644 samples/BitbucketStronglyTypedCoreReceiver/BitbucketPush.cs delete mode 100644 samples/BitbucketStronglyTypedCoreReceiver/BitbucketPushNotification.cs delete mode 100644 samples/BitbucketStronglyTypedCoreReceiver/BitbucketState.cs delete mode 100644 samples/BitbucketStronglyTypedCoreReceiver/BitbucketStronglyTypedCoreReceiver.csproj delete mode 100644 samples/BitbucketStronglyTypedCoreReceiver/Controllers/BitbucketController.cs delete mode 100644 samples/BitbucketStronglyTypedCoreReceiver/Program.cs delete mode 100644 samples/BitbucketStronglyTypedCoreReceiver/Startup.cs delete mode 100644 samples/BitbucketStronglyTypedCoreReceiver/appsettings.json delete mode 100644 samples/Directory.Build.props delete mode 100644 samples/DropboxCoreReceiver/Controllers/DropboxController.cs delete mode 100644 samples/DropboxCoreReceiver/DropboxCoreReceiver.csproj delete mode 100644 samples/DropboxCoreReceiver/Program.cs delete mode 100644 samples/DropboxCoreReceiver/Startup.cs delete mode 100644 samples/DynamicsCRMCoreReceiver/Controllers/DynamicsCRMController.cs delete mode 100644 samples/DynamicsCRMCoreReceiver/DynamicsCRMCoreReceiver.csproj delete mode 100644 samples/DynamicsCRMCoreReceiver/Program.cs delete mode 100644 samples/DynamicsCRMCoreReceiver/Startup.cs delete mode 100644 samples/DynamicsCRMCoreReceiver/appsettings.json delete mode 100644 samples/GitHubCoreReceiver/Controllers/GitHubController.cs delete mode 100644 samples/GitHubCoreReceiver/GitHubCoreReceiver.csproj delete mode 100644 samples/GitHubCoreReceiver/Program.cs delete mode 100644 samples/GitHubCoreReceiver/Startup.cs delete mode 100644 samples/KuduCoreReceiver/Controllers/KuduController.cs delete mode 100644 samples/KuduCoreReceiver/KuduCoreReceiver.csproj delete mode 100644 samples/KuduCoreReceiver/Program.cs delete mode 100644 samples/KuduCoreReceiver/Startup.cs delete mode 100644 samples/MailChimpCoreReceiver/Controllers/MailChimpController.cs delete mode 100644 samples/MailChimpCoreReceiver/MailChimpCoreReceiver.csproj delete mode 100644 samples/MailChimpCoreReceiver/Program.cs delete mode 100644 samples/MailChimpCoreReceiver/Startup.cs delete mode 100644 samples/PusherCoreReceiver/Controllers/PusherController.cs delete mode 100644 samples/PusherCoreReceiver/Program.cs delete mode 100644 samples/PusherCoreReceiver/PusherCoreReceiver.csproj delete mode 100644 samples/PusherCoreReceiver/Startup.cs delete mode 100644 samples/PusherCoreReceiver/appsettings.json delete mode 100644 samples/PusherCoreReceiver/wwwroot/index.html delete mode 100644 samples/SalesforceCoreReceiver/Controllers/SalesforceController.cs delete mode 100644 samples/SalesforceCoreReceiver/Program.cs delete mode 100644 samples/SalesforceCoreReceiver/SalesforceCoreReceiver.csproj delete mode 100644 samples/SalesforceCoreReceiver/Startup.cs delete mode 100644 samples/SalesforceCoreReceiver/appsettings.json delete mode 100644 samples/SlackCoreReceiver/Controllers/SlackController.cs delete mode 100644 samples/SlackCoreReceiver/Program.cs delete mode 100644 samples/SlackCoreReceiver/SlackCoreReceiver.csproj delete mode 100644 samples/SlackCoreReceiver/Startup.cs delete mode 100644 samples/SlackCoreReceiver/appsettings.json delete mode 100644 samples/StripeCoreReceiver/Controllers/StripeController.cs delete mode 100644 samples/StripeCoreReceiver/Program.cs delete mode 100644 samples/StripeCoreReceiver/Startup.cs delete mode 100644 samples/StripeCoreReceiver/StripeCoreReceiver.csproj delete mode 100644 samples/StripeCoreReceiver/appsettings.json delete mode 100644 src/Directory.Build.props delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/AzureAlertCondition.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/AzureAlertConstants.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/AzureAlertContext.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/AzureAlertNotification.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/AzureAlertWebHookAttribute.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/Extensions/AzureAlertMvcBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/Extensions/AzureAlertMvcCoreBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/Internal/AzureAlertServiceCollectionSetup.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/Metadata/AzureAlertMetadata.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert.csproj delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketAuthor.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketConstants.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketLink.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketParent.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketRepository.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketTarget.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketUser.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketWebHookAttribute.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Extensions/BitbucketMvcBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Extensions/BitbucketMvcCoreBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Internal/BitbucketServiceCollectionSetup.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Metadata/BitbucketMetadata.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket.csproj delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Properties/Resources.Designer.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Properties/Resources.resx delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/DropboxConstants.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/DropboxWebHookAttribute.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/Extensions/DropboxMvcBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/Extensions/DropboxMvcCoreBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/Filters/DropboxVerifySignatureFilter.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/Internal/DropboxServiceCollectionSetup.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/Metadata/DropboxMetadata.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox.csproj delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/DynamicsCRMConstants.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/DynamicsCRMWebHookAttribute.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/Extensions/DynamicsCRMMvcBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/Extensions/DynamicsCRMMvcCoreBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/Internal/DynamicsCRMServiceCollectionSetup.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/Metadata/DynamicsCRMMetadata.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM.csproj delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Extensions/GitHubMvcBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Extensions/GitHubMvcCoreBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Filters/GitHubVerifySignatureFilter.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/GitHubConstants.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/GitHubWebHookAttribute.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Internal/GitHubServiceCollectionSetup.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Metadata/GitHubMetadata.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Microsoft.AspNetCore.WebHooks.Receivers.GitHub.csproj delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Properties/AssemblyInfo.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Properties/Resources.Designer.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Properties/Resources.resx delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/Extensions/KuduMvcBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/Extensions/KuduMvcCoreBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/Internal/KuduServiceCollectionSetup.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/KuduConstants.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/KuduNotification.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/KuduWebHookAttribute.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/Metadata/KuduMetadata.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/Microsoft.AspNetCore.WebHooks.Receivers.Kudu.csproj delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/Extensions/MailChimpMvcBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/Extensions/MailChimpMvcCoreBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/Internal/MailChimpServiceCollectionSetup.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/MailChimpConstants.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/MailChimpWebHookAttribute.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/Metadata/MailChimpMetadata.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp.csproj delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Extensions/PusherMvcBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Extensions/PusherMvcCoreBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Filters/PusherVerifySignatureFilter.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Internal/PusherServiceCollectionSetup.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Metadata/PusherMetadata.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Microsoft.AspNetCore.WebHooks.Receivers.Pusher.csproj delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Properties/Resources.Designer.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Properties/Resources.resx delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/PusherConstants.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/PusherNotifications.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/PusherWebHookAttribute.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Extensions/SalesforceMvcBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Extensions/SalesforceMvcCoreBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Filters/SalesforceVerifyOrganizationIdFilter.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/ISalesforceResultCreator.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Internal/SalesforceResultCreator.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Internal/SalesforceServiceCollectionSetup.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Messages/FaultResponse.xml delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Messages/NotificationResponse.xml delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Metadata/SalesforceMetadata.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce.csproj delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/ModelBinding/SalesforceNotificationsModelBinder.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/ModelBinding/SalesforceNotificationsModelBinderProvider.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Properties/Resources.Designer.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Properties/Resources.resx delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/SalesforceConstants.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/SalesforceNamespaces.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/SalesforceNotifications.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/SalesforceWebHookAttribute.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Extensions/SlackMvcBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Extensions/SlackMvcCoreBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Filters/SlackVerifyTokenFilter.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Internal/SlackServiceCollectionSetup.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Metadata/SlackMetadata.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Microsoft.AspNetCore.WebHooks.Receivers.Slack.csproj delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Properties/Resources.Designer.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Properties/Resources.resx delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackAttachment.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackCommand.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackConstants.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackField.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackResponse.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackSlashResponse.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackWebHookAttribute.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Extensions/StripeMvcBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Extensions/StripeMvcCoreBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Filters/StripeTestEventRequestFilter.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Filters/StripeVerifyNotificationIdFilter.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Filters/StripeVerifySignatureFilter.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Internal/StripeServiceCollectionSetup.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Metadata/StripeMetadata.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Microsoft.AspNetCore.WebHooks.Receivers.Stripe.csproj delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/ModelBinding/UnixTimeConverter.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Properties/Resources.Designer.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Properties/Resources.resx delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/StripeConstants.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/StripeEvent.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/StripeEventData.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/StripeRequestData.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/StripeWebHookAttribute.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.Trello/Microsoft.AspNetCore.WebHooks.Receivers.Trello.csproj delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers.WordPress/Microsoft.AspNetCore.WebHooks.Receivers.WordPress.csproj delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/ApplicationModels/WebHookMetadataProvider.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/ApplicationModels/WebHookModelBindingProvider.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/ApplicationModels/WebHookRoutingProvider.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Extensions/WebHookMvcBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Extensions/WebHookMvcCoreBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Extensions/WebHookRouteDataExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookEventMapperFilter.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookGetRequestFilter.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookPingRequestFilter.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookReceiverExistsFilter.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookSecurityFilter.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookVerifyBodyTypeFilter.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookVerifyCodeFilter.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookVerifyMethodFilter.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookVerifyRequiredValueFilter.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookVerifySignatureFilter.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/GeneralWebHookAttribute.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/IWebHookReceiver.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/IWebHookRequestReader.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Internal/WebHookRequestReader.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Internal/WebHookServiceCollectionSetup.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookBindingMetadata.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookBodyTypeMetadata.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookBodyTypeMetadataService.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookEventFromBodyMetadata.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookEventMetadata.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookEventSelectorMetadata.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookGetRequestMetadata.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookMetadata.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookPingRequestMetadata.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookVerifyCodeMetadata.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/WebHookBodyType.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/WebHookMetadata.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/WebHookParameter.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/WebHookParameterType.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Microsoft.AspNetCore.WebHooks.Receivers.csproj delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Properties/AssemblyInfo.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Properties/Resources.Designer.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Properties/Resources.resx delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookEventMapperConstraint.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookEventNamesConstraint.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookIdConstraint.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookMultipleEventNamesConstraint.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookReceiverExistsConstraint.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookReceiverNameConstraint.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookSingleEventNamesConstraint.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/Utilities/WebHookHttpRequestUtilities.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/WebHookAttribute.cs delete mode 100644 src/Microsoft.AspNetCore.WebHooks.Receivers/WebHookConstants.cs delete mode 100644 src/shared/Utilities/ObjectPathUtilities.cs delete mode 100644 src/shared/Utilities/TrimmingTokenizer.cs delete mode 100644 test/Directory.Build.props delete mode 100644 test/Microsoft.AspNetCore.WebHooks.Receivers.Slack.Test/Microsoft.AspNetCore.WebHooks.Receivers.Slack.Test.csproj delete mode 100644 test/Microsoft.AspNetCore.WebHooks.Receivers.Slack.Test/SlackCommandTests.cs delete mode 100644 test/Microsoft.AspNetCore.WebHooks.Receivers.Stripe.Test/Filters/StripeVerifySignatureFilterTests.cs delete mode 100644 test/Microsoft.AspNetCore.WebHooks.Receivers.Stripe.Test/Microsoft.AspNetCore.WebHooks.Receivers.Stripe.Test.csproj delete mode 100644 test/Microsoft.AspNetCore.WebHooks.Receivers.Stripe.Test/ModelBinding/UnixTimeConverterTests.cs delete mode 100644 test/Microsoft.AspNetCore.shared.Test/Internal/TrimmingTokenizerTests.cs delete mode 100644 test/Microsoft.AspNetCore.shared.Test/Microsoft.AspNetCore.WebHooks.shared.Test.csproj delete mode 100644 tools/Directory.Build.props diff --git a/Directory.Build.props b/Directory.Build.props index ffb05d1..080cbd8 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,61 +1,3 @@ - - - - - - - - $([System.IO.Path]::GetFullPath( '$(MSBuildThisFileDirectory)' )) - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - $(MSBuildAllProjects);$(RepositoryRoot)version.props - - - - - Microsoft - Microsoft Corporation. - Copyright © Microsoft Corporation - true - true - - - false - - 7.1 - en-US - true - https://go.microsoft.com/fwlink/?LinkID=288859 - https://raw.githubusercontent.com/aspnet/Home/2.0.0/LICENSE.txt - https://asp.net - true - - - - - <_TwoDigitYear>$([MSBuild]::Subtract($([System.DateTime]::UtcNow.Year), 2000)) - <_ThreeDigitDayOfYear>$([System.DateTime]::UtcNow.DayOfYear.ToString().PadLeft(3, '0')) - $(_TwoDigitYear)$(_ThreeDigitDayOfYear) - - - - - Microsoft ASP.NET Core WebHooks - git - https://github.com/aspnet/WebHooks - true - - $(RepositoryRoot)tools\35MSSharedLib1024.snk - true - true - - - true - - - - - <_Parameter1>BuildNumber - <_Parameter2>$(BuildNumber) - - + + diff --git a/Directory.Build.targets b/Directory.Build.targets index 27f27dc..080cbd8 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,28 +1,3 @@ - - - - - - - $(RepositoryRoot)bin\$(Configuration)\ - - - $(RepositoryRoot)bin\$(PlatformName)\$(Configuration)\ - - - - - - - True - True - Resources.resx - - - - ResXFileCodeGenerator - Resources.Designer.cs - - + diff --git a/global.json b/global.json deleted file mode 100644 index 4d61027..0000000 --- a/global.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "sdk": { - "version": "2.0.0" - } -} \ No newline at end of file diff --git a/samples/AzureAlertCoreReceiver/AzureAlertCoreReceiver.csproj b/samples/AzureAlertCoreReceiver/AzureAlertCoreReceiver.csproj deleted file mode 100644 index 41d771f..0000000 --- a/samples/AzureAlertCoreReceiver/AzureAlertCoreReceiver.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - $(Configurations);CodeAnalysis - netcoreapp2.0 - - - - - - - - diff --git a/samples/AzureAlertCoreReceiver/Controllers/AzureAlertController.cs b/samples/AzureAlertCoreReceiver/Controllers/AzureAlertController.cs deleted file mode 100644 index ab98cea..0000000 --- a/samples/AzureAlertCoreReceiver/Controllers/AzureAlertController.cs +++ /dev/null @@ -1,48 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.WebHooks; - -namespace AzureAlertCoreReceiver.Controllers -{ - public class AzureAlertController : ControllerBase - { - [AzureAlertWebHook(Id = "It")] - public IActionResult AzureAlertForIt(string @event, AzureAlertNotification data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - // Get the notification status - var status = data.Status; - - // Get the notification name - var name = data.Context.Name; - - // Get the name of the metric that caused the event - var author = data.Context.Condition.MetricName; - - return Ok(); - } - - [AzureAlertWebHook] - public IActionResult AzureAlert(string id, string @event, AzureAlertNotification data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - // Get the notification status - var status = data.Status; - - // Get the notification name - var name = data.Context.Name; - - // Get the name of the metric that caused the event - var author = data.Context.Condition.MetricName; - - return Ok(); - } - } -} diff --git a/samples/AzureAlertCoreReceiver/Program.cs b/samples/AzureAlertCoreReceiver/Program.cs deleted file mode 100644 index 1c190ab..0000000 --- a/samples/AzureAlertCoreReceiver/Program.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; - -namespace AzureAlertCoreReceiver -{ - public class Program - { - public static void Main(string[] args) - { - BuildWebHost(args).Run(); - } - - public static IWebHost BuildWebHost(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup() - .Build(); - } -} diff --git a/samples/AzureAlertCoreReceiver/Startup.cs b/samples/AzureAlertCoreReceiver/Startup.cs deleted file mode 100644 index 7abcc25..0000000 --- a/samples/AzureAlertCoreReceiver/Startup.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; - -namespace AzureAlertCoreReceiver -{ - public class Startup - { - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) - { - services - .AddMvcCore() - .AddAzureAlertWebHooks(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseMvc(); - } - } -} diff --git a/samples/BitbucketCoreReceiver/BitbucketCoreReceiver.csproj b/samples/BitbucketCoreReceiver/BitbucketCoreReceiver.csproj deleted file mode 100644 index 9c9d08b..0000000 --- a/samples/BitbucketCoreReceiver/BitbucketCoreReceiver.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - $(Configurations);CodeAnalysis - netcoreapp2.0 - - - - - - - - diff --git a/samples/BitbucketCoreReceiver/Controllers/BitbucketController.cs b/samples/BitbucketCoreReceiver/Controllers/BitbucketController.cs deleted file mode 100644 index feeb61b..0000000 --- a/samples/BitbucketCoreReceiver/Controllers/BitbucketController.cs +++ /dev/null @@ -1,82 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.WebHooks; -using Microsoft.Extensions.Logging; -using Newtonsoft.Json.Linq; - -namespace BitbucketCoreReceiver.Controllers -{ - public class BitbucketController : ControllerBase - { - private readonly ILogger _logger; - - public BitbucketController(ILoggerFactory loggerFactory) - { - _logger = loggerFactory.CreateLogger(); - } - - [BitbucketWebHook(Id = "It")] - public IActionResult BitbucketForIt(string @event, string webHookId, JObject data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - _logger.LogInformation( - 0, - "{ControllerName} received '{EventName}' for '{Id}' and '{WebHookId}'.", - nameof(BitbucketController), - @event, - "It", - webHookId); - - return Ok(); - } - - [BitbucketWebHook(EventName = "repo:push")] - public IActionResult BitbucketForPush(string id, string webHookId, JObject data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - // Extract information about the repository - var repository = data["repository"].ToObject(); - - // Information about the user causing the event - var actor = data["actor"].ToObject(); - - // Information about the specific changes - foreach (var change in data["push"]["changes"]) - { - // The previous commit - var oldTarget = change["old"]["target"].ToObject(); - - // The new commit - var newTarget = change["new"]["target"].ToObject(); - } - - return Ok(); - } - - [BitbucketWebHook] - public IActionResult Bitbucket(string id, string @event, string webHookId, JObject data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - _logger.LogInformation( - 1, - "{ControllerName} received '{EventName}' for '{Id}' and '{WebHookId}'.", - nameof(BitbucketController), - @event, - id, - webHookId); - - return Ok(); - } - } -} \ No newline at end of file diff --git a/samples/BitbucketCoreReceiver/Program.cs b/samples/BitbucketCoreReceiver/Program.cs deleted file mode 100644 index 01bc18e..0000000 --- a/samples/BitbucketCoreReceiver/Program.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; - -namespace BitbucketCoreReceiver -{ - public class Program - { - public static void Main(string[] args) - { - BuildWebHost(args).Run(); - } - - public static IWebHost BuildWebHost(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup() - .Build(); - } -} diff --git a/samples/BitbucketCoreReceiver/Startup.cs b/samples/BitbucketCoreReceiver/Startup.cs deleted file mode 100644 index bef8d5b..0000000 --- a/samples/BitbucketCoreReceiver/Startup.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; - -namespace BitbucketCoreReceiver -{ - public class Startup - { - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) - { - services - .AddMvcCore() - .AddBitbucketWebHooks(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseMvc(); - } - } -} diff --git a/samples/BitbucketCoreReceiver/appsettings.json b/samples/BitbucketCoreReceiver/appsettings.json deleted file mode 100644 index 7c0cf1d..0000000 --- a/samples/BitbucketCoreReceiver/appsettings.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "Logging": { - "IncludeScopes": false, - "LogLevel": { - "Default": "Warning" - }, - "Console": { - "LogLevel": { - "BitbucketCoreReceiver": "Information", - "Default": "Warning", - "Microsoft": "Information" - } - } - } -} \ No newline at end of file diff --git a/samples/BitbucketStronglyTypedCoreReceiver/BitbucketChange.cs b/samples/BitbucketStronglyTypedCoreReceiver/BitbucketChange.cs deleted file mode 100644 index f687258..0000000 --- a/samples/BitbucketStronglyTypedCoreReceiver/BitbucketChange.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace BitbucketStronglyTypedCoreReceiver -{ - /// - /// Contains information sent about an individual change in a Bitbucket repo:push notification. Ignores - /// information such as links found at this level in the notification as well as a few - /// properties. - /// - public class BitbucketChange - { - [JsonProperty("old")] - public BitbucketState Old { get; set; } - - [JsonProperty("new")] - public BitbucketState New { get; set; } - - [JsonProperty("commits", Required = Required.Always)] - public IList Commits { get; } = new List(); - - [JsonProperty("truncated", Required = Required.Always)] - public bool AreCommitsTruncated { get; set; } - } -} diff --git a/samples/BitbucketStronglyTypedCoreReceiver/BitbucketCommit.cs b/samples/BitbucketStronglyTypedCoreReceiver/BitbucketCommit.cs deleted file mode 100644 index c7f1edd..0000000 --- a/samples/BitbucketStronglyTypedCoreReceiver/BitbucketCommit.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Microsoft.AspNetCore.WebHooks; -using Newtonsoft.Json; - -namespace BitbucketStronglyTypedCoreReceiver -{ - /// - /// Contains information sent about an individual commit in a Bitbucket repo:push notification. Ignores - /// information such as links found at this level in the notification. - /// - public class BitbucketCommit - { - [JsonProperty("author", Required = Required.Always)] - public BitbucketUser Author { get; set; } - - [JsonProperty("message", Required = Required.Always)] - public string Message { get; set; } - - [JsonProperty("hash", Required = Required.Always)] - public string Sha1Hash { get; set; } - - [JsonProperty("type", Required = Required.Always)] - public string Type { get; set; } - } -} diff --git a/samples/BitbucketStronglyTypedCoreReceiver/BitbucketPush.cs b/samples/BitbucketStronglyTypedCoreReceiver/BitbucketPush.cs deleted file mode 100644 index 9146e12..0000000 --- a/samples/BitbucketStronglyTypedCoreReceiver/BitbucketPush.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using Newtonsoft.Json; - -namespace BitbucketStronglyTypedCoreReceiver -{ - /// - /// Contains information sent about the push in a Bitbucket WebHook repo:push notification. - /// - public class BitbucketPush - { - [JsonProperty("changes", Required = Required.Always)] - [MinLength(1)] - public IList Changes { get; } = new List(); - } -} diff --git a/samples/BitbucketStronglyTypedCoreReceiver/BitbucketPushNotification.cs b/samples/BitbucketStronglyTypedCoreReceiver/BitbucketPushNotification.cs deleted file mode 100644 index a49d844..0000000 --- a/samples/BitbucketStronglyTypedCoreReceiver/BitbucketPushNotification.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Microsoft.AspNetCore.WebHooks; -using Newtonsoft.Json; - -namespace BitbucketStronglyTypedCoreReceiver -{ - /// - /// Contains information sent in a Bitbucket WebHook repo:push notification. - /// - public class BitbucketPushNotification - { - [JsonProperty("actor", Required = Required.Always)] - public BitbucketUser Actor { get; set; } - - [JsonProperty("repository", Required = Required.Always)] - public BitbucketRepository Repository { get; set; } - - [JsonProperty("push", Required = Required.Always)] - public BitbucketPush Push { get; set; } - } -} diff --git a/samples/BitbucketStronglyTypedCoreReceiver/BitbucketState.cs b/samples/BitbucketStronglyTypedCoreReceiver/BitbucketState.cs deleted file mode 100644 index 198449a..0000000 --- a/samples/BitbucketStronglyTypedCoreReceiver/BitbucketState.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Microsoft.AspNetCore.WebHooks; -using Newtonsoft.Json; - -namespace BitbucketStronglyTypedCoreReceiver -{ - /// - /// Contains information sent about the old or new state of an individual change in a Bitbucket - /// repo:push notification. Ignores information such as links found at this level in the notification. - /// - public class BitbucketState - { - [JsonProperty("type", Required = Required.Always)] - public string Type { get; set; } - - [JsonProperty("name", Required = Required.Always)] - public string Name { get; set; } - - [JsonProperty("target", Required = Required.Always)] - public BitbucketTarget Target { get; set; } - } -} diff --git a/samples/BitbucketStronglyTypedCoreReceiver/BitbucketStronglyTypedCoreReceiver.csproj b/samples/BitbucketStronglyTypedCoreReceiver/BitbucketStronglyTypedCoreReceiver.csproj deleted file mode 100644 index 9c9d08b..0000000 --- a/samples/BitbucketStronglyTypedCoreReceiver/BitbucketStronglyTypedCoreReceiver.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - $(Configurations);CodeAnalysis - netcoreapp2.0 - - - - - - - - diff --git a/samples/BitbucketStronglyTypedCoreReceiver/Controllers/BitbucketController.cs b/samples/BitbucketStronglyTypedCoreReceiver/Controllers/BitbucketController.cs deleted file mode 100644 index 6d94ea8..0000000 --- a/samples/BitbucketStronglyTypedCoreReceiver/Controllers/BitbucketController.cs +++ /dev/null @@ -1,82 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.WebHooks; -using Microsoft.Extensions.Logging; -using Newtonsoft.Json.Linq; - -namespace BitbucketStronglyTypedCoreReceiver.Controllers -{ - public class BitbucketController : ControllerBase - { - private readonly ILogger _logger; - - public BitbucketController(ILoggerFactory loggerFactory) - { - _logger = loggerFactory.CreateLogger(); - } - - [BitbucketWebHook(Id = "It")] - public IActionResult BitbucketForIt(string @event, string webHookId, JObject data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - _logger.LogInformation( - 0, - "{ControllerName} received '{EventName}' for '{Id}' and '{WebHookId}'.", - nameof(BitbucketController), - @event, - "It", - webHookId); - - return Ok(); - } - - [BitbucketWebHook(EventName = "repo:push")] - public IActionResult BitbucketForPush(string id, string webHookId, BitbucketPushNotification data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - // Extract information about the repository - var repository = data.Repository; - - // Information about the user causing the event - var actor = data.Actor; - - // Information about the specific changes - foreach (var change in data.Push.Changes) - { - // The previous commit - var oldTarget = change.Old.Target; - - // The new commit - var newTarget = change.New.Target; - } - - return Ok(); - } - - [BitbucketWebHook] - public IActionResult Bitbucket(string id, string @event, string webHookId, JObject data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - _logger.LogInformation( - 1, - "{ControllerName} received '{EventName}' for '{Id}' and '{WebHookId}'.", - nameof(BitbucketController), - @event, - id, - webHookId); - - return Ok(); - } - } -} \ No newline at end of file diff --git a/samples/BitbucketStronglyTypedCoreReceiver/Program.cs b/samples/BitbucketStronglyTypedCoreReceiver/Program.cs deleted file mode 100644 index 2e6e8e5..0000000 --- a/samples/BitbucketStronglyTypedCoreReceiver/Program.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; - -namespace BitbucketStronglyTypedCoreReceiver -{ - public class Program - { - public static void Main(string[] args) - { - BuildWebHost(args).Run(); - } - - public static IWebHost BuildWebHost(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup() - .Build(); - } -} diff --git a/samples/BitbucketStronglyTypedCoreReceiver/Startup.cs b/samples/BitbucketStronglyTypedCoreReceiver/Startup.cs deleted file mode 100644 index 7ee7671..0000000 --- a/samples/BitbucketStronglyTypedCoreReceiver/Startup.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; - -namespace BitbucketStronglyTypedCoreReceiver -{ - public class Startup - { - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) - { - services - .AddMvcCore() - .AddBitbucketWebHooks(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseMvc(); - } - } -} diff --git a/samples/BitbucketStronglyTypedCoreReceiver/appsettings.json b/samples/BitbucketStronglyTypedCoreReceiver/appsettings.json deleted file mode 100644 index 74dd035..0000000 --- a/samples/BitbucketStronglyTypedCoreReceiver/appsettings.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "Logging": { - "IncludeScopes": false, - "LogLevel": { - "Default": "Warning" - }, - "Console": { - "LogLevel": { - "BitbucketStronglyTypedCoreReceiver": "Information", - "Default": "Warning", - "Microsoft": "Information" - } - } - } -} \ No newline at end of file diff --git a/samples/Directory.Build.props b/samples/Directory.Build.props deleted file mode 100644 index aa25ed0..0000000 --- a/samples/Directory.Build.props +++ /dev/null @@ -1,12 +0,0 @@ - - - <_ImportParentFile>false - <_ImportParentFile Condition="$(MSBuildProjectName.EndsWith( 'CoreReceiver' ))">true - - - - - - false - - diff --git a/samples/DropboxCoreReceiver/Controllers/DropboxController.cs b/samples/DropboxCoreReceiver/Controllers/DropboxController.cs deleted file mode 100644 index 4dc6068..0000000 --- a/samples/DropboxCoreReceiver/Controllers/DropboxController.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.WebHooks; -using Newtonsoft.Json.Linq; - -namespace DropboxCoreReceiver.Controllers -{ - public class DropboxController : ControllerBase - { - [DropboxWebHook(Id = "It")] - public IActionResult DropboxForIt(JObject data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - return Ok(); - } - - [DropboxWebHook] - public IActionResult Dropbox(string id, JObject data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - return Ok(); - } - } -} \ No newline at end of file diff --git a/samples/DropboxCoreReceiver/DropboxCoreReceiver.csproj b/samples/DropboxCoreReceiver/DropboxCoreReceiver.csproj deleted file mode 100644 index 834db13..0000000 --- a/samples/DropboxCoreReceiver/DropboxCoreReceiver.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - $(Configurations);CodeAnalysis - netcoreapp2.0 - - - - - - - - diff --git a/samples/DropboxCoreReceiver/Program.cs b/samples/DropboxCoreReceiver/Program.cs deleted file mode 100644 index 91fe7bf..0000000 --- a/samples/DropboxCoreReceiver/Program.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; - -namespace DropboxCoreReceiver -{ - public class Program - { - public static void Main(string[] args) - { - BuildWebHost(args).Run(); - } - - public static IWebHost BuildWebHost(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup() - .Build(); - } -} diff --git a/samples/DropboxCoreReceiver/Startup.cs b/samples/DropboxCoreReceiver/Startup.cs deleted file mode 100644 index 6a43bce..0000000 --- a/samples/DropboxCoreReceiver/Startup.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; - -namespace DropboxCoreReceiver -{ - public class Startup - { - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) - { - services - .AddMvcCore() - .AddDropboxWebHooks(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseMvc(); - } - } -} diff --git a/samples/DynamicsCRMCoreReceiver/Controllers/DynamicsCRMController.cs b/samples/DynamicsCRMCoreReceiver/Controllers/DynamicsCRMController.cs deleted file mode 100644 index 6c63541..0000000 --- a/samples/DynamicsCRMCoreReceiver/Controllers/DynamicsCRMController.cs +++ /dev/null @@ -1,53 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.WebHooks; -using Microsoft.Extensions.Logging; -using Newtonsoft.Json.Linq; - -namespace DynamicsCRMCoreReceiver.Controllers -{ - public class DynamicsCRMController : ControllerBase - { - private readonly ILogger _logger; - - public DynamicsCRMController(ILoggerFactory loggerFactory) - { - _logger = loggerFactory.CreateLogger(); - } - - [DynamicsCRMWebHook(Id = "It")] - public IActionResult DynamicsCRMForIt(string @event, JObject data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - _logger.LogInformation( - 0, - "{ControllerName} received '{MessageName}' for '{Id}'.", - nameof(DynamicsCRMController), - @event, - "It"); - - return Ok(); - } - - [DynamicsCRMWebHook] - public IActionResult DynamicsCRM(string id, string @event, JObject data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - _logger.LogInformation( - 1, - "{ControllerName} received '{MessageName}' for '{Id}'.", - nameof(DynamicsCRMController), - @event, - id); - - return Ok(); - } - } -} diff --git a/samples/DynamicsCRMCoreReceiver/DynamicsCRMCoreReceiver.csproj b/samples/DynamicsCRMCoreReceiver/DynamicsCRMCoreReceiver.csproj deleted file mode 100644 index 24cd3ca..0000000 --- a/samples/DynamicsCRMCoreReceiver/DynamicsCRMCoreReceiver.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - $(Configurations);CodeAnalysis - netcoreapp2.0 - - - - - - - - diff --git a/samples/DynamicsCRMCoreReceiver/Program.cs b/samples/DynamicsCRMCoreReceiver/Program.cs deleted file mode 100644 index 67d6029..0000000 --- a/samples/DynamicsCRMCoreReceiver/Program.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; - -namespace DynamicsCRMCoreReceiver -{ - public class Program - { - public static void Main(string[] args) - { - BuildWebHost(args).Run(); - } - - public static IWebHost BuildWebHost(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup() - .Build(); - } -} diff --git a/samples/DynamicsCRMCoreReceiver/Startup.cs b/samples/DynamicsCRMCoreReceiver/Startup.cs deleted file mode 100644 index 2d12b30..0000000 --- a/samples/DynamicsCRMCoreReceiver/Startup.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; - -namespace DynamicsCRMCoreReceiver -{ - public class Startup - { - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) - { - services - .AddMvcCore() - .AddDynamicsCRMWebHooks(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseMvc(); - } - } -} diff --git a/samples/DynamicsCRMCoreReceiver/appsettings.json b/samples/DynamicsCRMCoreReceiver/appsettings.json deleted file mode 100644 index a948f1b..0000000 --- a/samples/DynamicsCRMCoreReceiver/appsettings.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "Logging": { - "IncludeScopes": false, - "LogLevel": { - "Default": "Warning" - }, - "Console": { - "LogLevel": { - "DynamicsCRMCoreReceiver": "Information", - "Default": "Warning", - "Microsoft": "Information" - } - } - } -} \ No newline at end of file diff --git a/samples/GitHubCoreReceiver/Controllers/GitHubController.cs b/samples/GitHubCoreReceiver/Controllers/GitHubController.cs deleted file mode 100644 index 2488cd1..0000000 --- a/samples/GitHubCoreReceiver/Controllers/GitHubController.cs +++ /dev/null @@ -1,64 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.WebHooks; -using Newtonsoft.Json.Linq; - -namespace GitHubCoreReceiver.Controllers -{ - public class GitHubController : ControllerBase - { - [GitHubWebHook(EventName = "push", Id = "It")] - public IActionResult HandlerForItsPushes(string[] events, JObject data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - return Ok(); - } - - [GitHubWebHook(Id = "It")] - public IActionResult HandlerForIt(string[] events, JObject data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - return Ok(); - } - - [GitHubWebHook(EventName = "push")] - public IActionResult HandlerForPush(string id, JObject data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - return Ok(); - } - - [GitHubWebHook] - public IActionResult GitHubHandler(string id, string @event, JObject data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - return Ok(); - } - - [GeneralWebHook] - public IActionResult FallbackHandler(string receiverName, string id, string eventName, JObject data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - return Ok(); - } - } -} diff --git a/samples/GitHubCoreReceiver/GitHubCoreReceiver.csproj b/samples/GitHubCoreReceiver/GitHubCoreReceiver.csproj deleted file mode 100644 index 510a455..0000000 --- a/samples/GitHubCoreReceiver/GitHubCoreReceiver.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - $(Configurations);CodeAnalysis - netcoreapp2.0 - - - - - - - - diff --git a/samples/GitHubCoreReceiver/Program.cs b/samples/GitHubCoreReceiver/Program.cs deleted file mode 100644 index 008fb7d..0000000 --- a/samples/GitHubCoreReceiver/Program.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; - -namespace GitHubCoreReceiver -{ - public class Program - { - public static void Main(string[] args) - { - BuildWebHost(args).Run(); - } - - public static IWebHost BuildWebHost(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup() - .Build(); - } -} diff --git a/samples/GitHubCoreReceiver/Startup.cs b/samples/GitHubCoreReceiver/Startup.cs deleted file mode 100644 index e13786d..0000000 --- a/samples/GitHubCoreReceiver/Startup.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; - -namespace GitHubCoreReceiver -{ - public class Startup - { - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) - { - services - .AddMvcCore() - .AddGitHubWebHooks(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseMvc(); - } - } -} diff --git a/samples/KuduCoreReceiver/Controllers/KuduController.cs b/samples/KuduCoreReceiver/Controllers/KuduController.cs deleted file mode 100644 index 9261ff6..0000000 --- a/samples/KuduCoreReceiver/Controllers/KuduController.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.WebHooks; - -namespace KuduCoreReceiver.Controllers -{ - public class KuduController : ControllerBase - { - [KuduWebHook(Id = "It")] - public IActionResult KuduForIt(string @event, KuduNotification data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - // Get the notification message - var message = data.Message; - - // Get the notification author - var author = data.Author; - - return Ok(); - } - - [KuduWebHook] - public IActionResult Kudu(string id, string @event, KuduNotification data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - // Get the notification message - var message = data.Message; - - // Get the notification author - var author = data.Author; - - return Ok(); - } - } -} diff --git a/samples/KuduCoreReceiver/KuduCoreReceiver.csproj b/samples/KuduCoreReceiver/KuduCoreReceiver.csproj deleted file mode 100644 index 48b6c50..0000000 --- a/samples/KuduCoreReceiver/KuduCoreReceiver.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - $(Configurations);CodeAnalysis - netcoreapp2.0 - - - - - - - - diff --git a/samples/KuduCoreReceiver/Program.cs b/samples/KuduCoreReceiver/Program.cs deleted file mode 100644 index 8de1a9b..0000000 --- a/samples/KuduCoreReceiver/Program.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; - -namespace KuduCoreReceiver -{ - public class Program - { - public static void Main(string[] args) - { - BuildWebHost(args).Run(); - } - - public static IWebHost BuildWebHost(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup() - .Build(); - } -} diff --git a/samples/KuduCoreReceiver/Startup.cs b/samples/KuduCoreReceiver/Startup.cs deleted file mode 100644 index 2b5a275..0000000 --- a/samples/KuduCoreReceiver/Startup.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; - -namespace KuduCoreReceiver -{ - public class Startup - { - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) - { - services - .AddMvcCore() - .AddKuduWebHooks(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseMvc(); - } - } -} diff --git a/samples/MailChimpCoreReceiver/Controllers/MailChimpController.cs b/samples/MailChimpCoreReceiver/Controllers/MailChimpController.cs deleted file mode 100644 index 3da1cc5..0000000 --- a/samples/MailChimpCoreReceiver/Controllers/MailChimpController.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.WebHooks; - -namespace MailChimpCoreReceiver.Controllers -{ - public class MailChimpController : ControllerBase - { - [MailChimpWebHook(Id = "It")] - public IActionResult MailChimpForIt(string @event, IFormCollection data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - return Ok(); - } - - [MailChimpWebHook] - public IActionResult MailChimp(string id, string @event, IFormCollection data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - return Ok(); - } - } -} diff --git a/samples/MailChimpCoreReceiver/MailChimpCoreReceiver.csproj b/samples/MailChimpCoreReceiver/MailChimpCoreReceiver.csproj deleted file mode 100644 index e1465fe..0000000 --- a/samples/MailChimpCoreReceiver/MailChimpCoreReceiver.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - $(Configurations);CodeAnalysis - netcoreapp2.0 - - - - - - - - diff --git a/samples/MailChimpCoreReceiver/Program.cs b/samples/MailChimpCoreReceiver/Program.cs deleted file mode 100644 index cbc7638..0000000 --- a/samples/MailChimpCoreReceiver/Program.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; - -namespace MailChimpCoreReceiver -{ - public class Program - { - public static void Main(string[] args) - { - BuildWebHost(args).Run(); - } - - public static IWebHost BuildWebHost(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup() - .Build(); - } -} diff --git a/samples/MailChimpCoreReceiver/Startup.cs b/samples/MailChimpCoreReceiver/Startup.cs deleted file mode 100644 index 303b446..0000000 --- a/samples/MailChimpCoreReceiver/Startup.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; - -namespace MailChimpCoreReceiver -{ - public class Startup - { - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) - { - services - .AddMvcCore() - .AddMailChimpWebHooks(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseMvc(); - } - } -} diff --git a/samples/PusherCoreReceiver/Controllers/PusherController.cs b/samples/PusherCoreReceiver/Controllers/PusherController.cs deleted file mode 100644 index 7cf3e2c..0000000 --- a/samples/PusherCoreReceiver/Controllers/PusherController.cs +++ /dev/null @@ -1,164 +0,0 @@ -using System; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.WebHooks; -using Microsoft.Extensions.Logging; -using Newtonsoft.Json.Linq; - -namespace PusherCoreReceiver.Controllers -{ - public class PusherController : ControllerBase - { - private readonly ILogger _logger; - - public PusherController(ILoggerFactory loggerFactory) - { - _logger = loggerFactory.CreateLogger(); - } - - [PusherWebHook(Id = "It")] - public IActionResult PusherForIt(string[] eventNames, PusherNotifications data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - // Get the notification creation timestamp. - var createdAtUnix = data.CreatedAt; - var createdAt = DateTimeOffset.FromUnixTimeMilliseconds(createdAtUnix); - _logger.LogInformation( - 0, - "{ControllerName} received {Count} notifications and {EventCount} events created at '{CreatedAt}'.", - nameof(PusherController), - data.Events.Count, - eventNames.Length, - createdAt.ToString("o")); - for (var i = 0; i < eventNames.Length; i++) - { - _logger.LogInformation( - 1, - "Event {Index} was '{EventName}'.", - i, - eventNames[i]); - } - - // Get details of the individual notifications. - var index = 0; - foreach (var @event in data.Events) - { - if (@event.TryGetValue(PusherConstants.EventNamePropertyName, out var eventName)) - { - if (@event.TryGetValue(PusherConstants.ChannelNamePropertyName, out var channelName)) - { - _logger.LogInformation( - 2, - "Event {EventNumber} has {Count} properties, including name '{EventName}' and channel " + - "'{ChannelName}'.", - index, - @event.Count, - eventName, - channelName); - } - else - { - _logger.LogInformation( - 3, - "Event {EventNumber} has {Count} properties, including name '{EventName}'.", - index, - @event.Count, - eventName); - } - } - else - { - _logger.LogError( - 4, - "Event {EventNumber} has {Count} properties but does not contain a {PropertyName} property.", - index, - @event.Count, - PusherConstants.EventNamePropertyName); - } - - index++; - } - - return Ok(); - } - - [PusherWebHook] - public IActionResult Pusher(string id, string[] eventNames, JObject data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - // Get the notification creation timestamp. - var createdAtUnix = data.Value(PusherConstants.EventRequestCreatedAtPropertyName); - var createdAt = DateTimeOffset.FromUnixTimeMilliseconds(createdAtUnix); - var events = data.Value(PusherConstants.EventRequestPropertyContainerName); - _logger.LogInformation( - 5, - "{ControllerName} / '{Id}' received {Count} notifications and {EventCount} events created at " + - "'{CreatedAt}'.", - nameof(PusherController), - id, - events.Count, - eventNames.Length, - createdAt.ToString("o")); - for (var i = 0; i < eventNames.Length; i++) - { - _logger.LogInformation( - 6, - "Event {Index} was '{EventName}'.", - i, - eventNames[i]); - } - - // Get details of the individual notifications. - var eventEnumerable = events.Values(); - var index = 0; - foreach (var @event in eventEnumerable) - { - var eventName = @event.Value(PusherConstants.EventNamePropertyName); - if (!string.IsNullOrEmpty(eventName)) - { - var channelName = @event.Value(PusherConstants.EventNamePropertyName); - if (!string.IsNullOrEmpty(channelName)) - { - _logger.LogInformation( - 7, - "Event {EventNumber} has {Count} properties, including name '{EventName}' and channel " + - "'{ChannelName}'.", - index, - @event.Count, - eventName, - channelName); - } - else - { - _logger.LogInformation( - 8, - "Event {EventNumber} has {Count} properties, including name '{EventName}'.", - index, - @event.Count, - eventName); - } - } - else - { - _logger.LogError( - 9, - "Event {EventNumber} has {Count} properties but does not contain a {PropertyName} property.", - index, - @event.Count, - PusherConstants.EventNamePropertyName); - } - - index++; - } - - return Ok(); - } - } -} diff --git a/samples/PusherCoreReceiver/Program.cs b/samples/PusherCoreReceiver/Program.cs deleted file mode 100644 index 4dcdd78..0000000 --- a/samples/PusherCoreReceiver/Program.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; - -namespace PusherCoreReceiver -{ - public class Program - { - public static void Main(string[] args) - { - BuildWebHost(args).Run(); - } - - public static IWebHost BuildWebHost(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup() - .Build(); - } -} diff --git a/samples/PusherCoreReceiver/PusherCoreReceiver.csproj b/samples/PusherCoreReceiver/PusherCoreReceiver.csproj deleted file mode 100644 index c6d0879..0000000 --- a/samples/PusherCoreReceiver/PusherCoreReceiver.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - $(Configurations);CodeAnalysis - netcoreapp2.0 - - - - - - - - - - - - PreserveNewest - - - diff --git a/samples/PusherCoreReceiver/Startup.cs b/samples/PusherCoreReceiver/Startup.cs deleted file mode 100644 index 89f47ae..0000000 --- a/samples/PusherCoreReceiver/Startup.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; - -namespace PusherCoreReceiver -{ - public class Startup - { - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) - { - services - .AddMvcCore() - .AddPusherWebHooks(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app - .UseDefaultFiles() - .UseStaticFiles() - .UseMvc(); - } - } -} diff --git a/samples/PusherCoreReceiver/appsettings.json b/samples/PusherCoreReceiver/appsettings.json deleted file mode 100644 index 8e99371..0000000 --- a/samples/PusherCoreReceiver/appsettings.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "Logging": { - "IncludeScopes": false, - "LogLevel": { - "Default": "Warning" - }, - "Console": { - "LogLevel": { - "PusherCoreReceiver": "Information", - "Default": "Warning", - "Microsoft": "Information" - } - } - } -} \ No newline at end of file diff --git a/samples/PusherCoreReceiver/wwwroot/index.html b/samples/PusherCoreReceiver/wwwroot/index.html deleted file mode 100644 index dd88246..0000000 --- a/samples/PusherCoreReceiver/wwwroot/index.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - Microsoft ASP.NET Core Pusher WebHooks receiver sample - - - -

Microsoft ASP.NET Core Pusher WebHooks receiver sample

- -

- This sample illustrates how to wire up a Pusher WebHooks receiver. A sample WebHook URI is: - https://{host}/api/webhooks/incoming/pusher/{id} -

- -

- Set WebHooks:Pusher:SecretKey:{id}:{application key} configuration values to the corresponding - secret keys. That is, match the Pusher application key / secret key pairs and optionally use IDs to - differentiate between multiple WebHooks. -

- -

- Please see Pusher WebHooks for more information. -

- - diff --git a/samples/SalesforceCoreReceiver/Controllers/SalesforceController.cs b/samples/SalesforceCoreReceiver/Controllers/SalesforceController.cs deleted file mode 100644 index 4eaf0e2..0000000 --- a/samples/SalesforceCoreReceiver/Controllers/SalesforceController.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System.Linq; -using System.Threading.Tasks; -using System.Xml.Linq; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.WebHooks; -using Microsoft.Extensions.Logging; - -namespace SalesforceCoreReceiver.Controllers -{ - public class SalesforceController : ControllerBase - { - private readonly ILogger _logger; - private readonly ISalesforceResultCreator _resultCreator; - - public SalesforceController(ILoggerFactory loggerFactory, ISalesforceResultCreator resultCreator) - { - _logger = loggerFactory.CreateLogger(); - _resultCreator = resultCreator; - } - - [SalesforceWebHook(Id = "It")] - public async Task SalesforceForIt(string @event, XElement data) - { - if (!ModelState.IsValid) - { - return await _resultCreator.GetFailedResultAsync("Model binding failed."); - } - - return await _resultCreator.GetSuccessResultAsync(); - } - - [SalesforceWebHook] - public async Task Salesforce(string id, string @event, SalesforceNotifications data) - { - if (!ModelState.IsValid) - { - return await _resultCreator.GetFailedResultAsync("Model binding failed."); - } - - _logger.LogInformation( - 0, - "{ControllerName} / '{ReceiverId}' received {Count} notifications with ActionId '{ActionId}' (event " + - "'{EventName}').", - nameof(SalesforceController), - id, - data.Notifications.Count(), - data.ActionId, - @event); - _logger.LogInformation( - 1, - "Data contains OrganizationId '{OrganizationId}' and SessionId '{SessionId}'.", - data.OrganizationId, - data.SessionId); - _logger.LogInformation( - 2, - "Contained URLs include EnterpriseUrl '{EnterpriseUrl}' and PartnerUrl '{PartnerUrl}'.", - data.EnterpriseUrl, - data.PartnerUrl); - - var index = 0; - foreach (var notification in data.Notifications) - { - _logger.LogInformation( - 3, - "Notification #{Number} contained {Count} values.", - index, - notification.Count); - index++; - } - - return await _resultCreator.GetSuccessResultAsync(); - } - } -} diff --git a/samples/SalesforceCoreReceiver/Program.cs b/samples/SalesforceCoreReceiver/Program.cs deleted file mode 100644 index 4f4e903..0000000 --- a/samples/SalesforceCoreReceiver/Program.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; - -namespace SalesforceCoreReceiver -{ - public class Program - { - public static void Main(string[] args) - { - BuildWebHost(args).Run(); - } - - public static IWebHost BuildWebHost(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup() - .Build(); - } -} diff --git a/samples/SalesforceCoreReceiver/SalesforceCoreReceiver.csproj b/samples/SalesforceCoreReceiver/SalesforceCoreReceiver.csproj deleted file mode 100644 index e6fb9b5..0000000 --- a/samples/SalesforceCoreReceiver/SalesforceCoreReceiver.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - $(Configurations);CodeAnalysis - netcoreapp2.0 - - - - - - - - diff --git a/samples/SalesforceCoreReceiver/Startup.cs b/samples/SalesforceCoreReceiver/Startup.cs deleted file mode 100644 index 1779ae9..0000000 --- a/samples/SalesforceCoreReceiver/Startup.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; - -namespace SalesforceCoreReceiver -{ - public class Startup - { - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) - { - services - .AddMvcCore() - .AddSalesforceWebHooks(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseMvc(); - } - } -} diff --git a/samples/SalesforceCoreReceiver/appsettings.json b/samples/SalesforceCoreReceiver/appsettings.json deleted file mode 100644 index a633ec1..0000000 --- a/samples/SalesforceCoreReceiver/appsettings.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "Logging": { - "IncludeScopes": false, - "LogLevel": { - "Default": "Warning" - }, - "Console": { - "LogLevel": { - "SalesforceCoreReceiver": "Information", - "Default": "Warning", - "Microsoft": "Information" - } - } - } -} \ No newline at end of file diff --git a/samples/SlackCoreReceiver/Controllers/SlackController.cs b/samples/SlackCoreReceiver/Controllers/SlackController.cs deleted file mode 100644 index 65c390f..0000000 --- a/samples/SlackCoreReceiver/Controllers/SlackController.cs +++ /dev/null @@ -1,163 +0,0 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.WebHooks; -using Microsoft.Extensions.Logging; - -namespace SlackCoreReceiver.Controllers -{ - public class SlackController : ControllerBase - { - private readonly ILogger _logger; - - public SlackController(ILoggerFactory loggerFactory) - { - _logger = loggerFactory.CreateLogger(); - } - - [SlackWebHook(Id = "command")] - public IActionResult SlackForCommand(string @event, string subtext, IFormCollection data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - _logger.LogInformation( - 0, - "{ControllerName} / '{ReceiverId}' received {Count} properties with event '{EventName}').", - nameof(SlackController), - "command", - data.Count, - @event); - - string channel = data[SlackConstants.ChannelRequestFieldName]; - string command = data[SlackConstants.CommandRequestFieldName]; - string trigger = data[SlackConstants.TriggerRequestFieldName]; - _logger.LogInformation( - 1, - "Data contains channel '{ChannelName}', command '{Command}', and trigger '{Trigger}'.", - channel, - command, - trigger); - - string text = data[SlackConstants.TextRequestFieldName]; - _logger.LogInformation( - 2, - "Data contains text '{Text}' and subtext '{Subtext}'.", - text, - subtext); - - var slashCommand = SlackCommand.ParseActionWithValue(command); - - // Ignore an error parsing the remainder of the command except to keep that action value together. - var actionValue = slashCommand.Value; - var actionValueName = "value"; - var (parameters, error) = SlackCommand.ParseParameters(slashCommand.Value); - if (error == null) - { - actionValue = SlackCommand.GetNormalizedParameterString(parameters); - actionValueName = "parameters"; - } - - // Create the response. - var reply = $"Received slash command '{command}' with action '{slashCommand.Key}' and {actionValueName} " + - $"'{actionValue}'."; - - // Slash responses can be augmented with attachments containing data, images, and more. - var attachment = new SlackAttachment("Attachment Text", "Fallback description") - { - Color = "#439FE0", - Pretext = "Hello from ASP.NET WebHooks!", - Title = "Attachment title", - }; - - // Slash attachments can contain tabular data as well - attachment.Fields.Add(new SlackField("Field1", "1234")); - attachment.Fields.Add(new SlackField("Field2", "5678")); - - return new JsonResult(new SlackSlashResponse(reply, attachment)); - } - - [SlackWebHook(Id = "trigger")] - public IActionResult SlackForTrigger(string @event, string subtext, IFormCollection data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - _logger.LogInformation( - 3, - "{ControllerName} / '{ReceiverId}' received {Count} properties with event '{EventName}').", - nameof(SlackController), - "trigger", - data.Count, - @event); - - var channel = data[SlackConstants.ChannelRequestFieldName]; - var command = data[SlackConstants.CommandRequestFieldName]; - var trigger = data[SlackConstants.TriggerRequestFieldName]; - _logger.LogInformation( - 4, - "Data contains channel '{ChannelName}', command '{Command}', and trigger '{Trigger}'.", - channel, - command, - trigger); - - var text = data[SlackConstants.TextRequestFieldName]; - _logger.LogInformation( - 5, - "Data contains text '{Text}' and subtext '{Subtext}'.", - text, - subtext); - - // Create the response. - var triggerCommand = SlackCommand.ParseActionWithValue(subtext); - - // Information can be returned using a SlackResponse. - var reply = string.Format( - "Received trigger '{0}' with action '{1}' and value '{2}'", - trigger, - triggerCommand.Key, - triggerCommand.Value); - - return new JsonResult(new SlackResponse(reply)); - } - - [SlackWebHook] - public IActionResult Slack(string id, string @event, string subtext, IFormCollection data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - _logger.LogInformation( - 6, - "{ControllerName} / '{ReceiverId}' received {Count} properties with event '{EventName}').", - nameof(SlackController), - id, - data.Count, - @event); - - var channel = data[SlackConstants.ChannelRequestFieldName]; - var command = data[SlackConstants.CommandRequestFieldName]; - var trigger = data[SlackConstants.TriggerRequestFieldName]; - _logger.LogInformation( - 7, - "Data contains channel '{ChannelName}', command '{Command}', and trigger '{Trigger}'.", - channel, - command, - trigger); - - var text = data[SlackConstants.TextRequestFieldName]; - _logger.LogInformation( - 8, - "Data contains text '{Text}' and subtext '{Subtext}'.", - text, - subtext); - - return Ok(); - } - } -} diff --git a/samples/SlackCoreReceiver/Program.cs b/samples/SlackCoreReceiver/Program.cs deleted file mode 100644 index 3a921cb..0000000 --- a/samples/SlackCoreReceiver/Program.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; - -namespace SlackCoreReceiver -{ - public class Program - { - public static void Main(string[] args) - { - BuildWebHost(args).Run(); - } - - public static IWebHost BuildWebHost(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup() - .Build(); - } -} diff --git a/samples/SlackCoreReceiver/SlackCoreReceiver.csproj b/samples/SlackCoreReceiver/SlackCoreReceiver.csproj deleted file mode 100644 index 0895a51..0000000 --- a/samples/SlackCoreReceiver/SlackCoreReceiver.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - $(Configurations);CodeAnalysis - netcoreapp2.0 - - - - - - - - diff --git a/samples/SlackCoreReceiver/Startup.cs b/samples/SlackCoreReceiver/Startup.cs deleted file mode 100644 index 1666ec8..0000000 --- a/samples/SlackCoreReceiver/Startup.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; - -namespace SlackCoreReceiver -{ - public class Startup - { - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) - { - services - .AddMvcCore() - .AddSlackWebHooks(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseMvc(); - } - } -} diff --git a/samples/SlackCoreReceiver/appsettings.json b/samples/SlackCoreReceiver/appsettings.json deleted file mode 100644 index 96893ae..0000000 --- a/samples/SlackCoreReceiver/appsettings.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "Logging": { - "IncludeScopes": false, - "LogLevel": { - "Default": "Warning" - }, - "Console": { - "LogLevel": { - "SlackCoreReceiver": "Information", - "Default": "Warning", - "Microsoft": "Information" - } - } - } -} \ No newline at end of file diff --git a/samples/StripeCoreReceiver/Controllers/StripeController.cs b/samples/StripeCoreReceiver/Controllers/StripeController.cs deleted file mode 100644 index ba813b7..0000000 --- a/samples/StripeCoreReceiver/Controllers/StripeController.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.WebHooks; -using Microsoft.Extensions.Logging; -using Newtonsoft.Json.Linq; - -namespace StripeCoreReceiver.Controllers -{ - public class StripeController : ControllerBase - { - private readonly ILogger _logger; - - public StripeController(ILoggerFactory loggerFactory) - { - _logger = loggerFactory.CreateLogger(); - } - - [StripeWebHook(Id = "It")] - public IActionResult StripeForIt(string @event, string notificationId, JObject data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - return Ok(); - } - - [StripeWebHook] - public IActionResult Stripe(string id, string @event, string notificationId, StripeEvent data) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - _logger.LogInformation( - 0, - "{ControllerName} / '{ReceiverId}' received a '{EventType}' notification (event '{EventName}').", - nameof(StripeController), - id, - data.EventType, - @event); - - _logger.LogInformation( - 1, - "Data created at '{Created}' and contains Notification ID '{Id}' / '{NotificationId}', Live mode " + - "'{DetailsLiveMode}', and Request ID '{RequestId}'.", - data.Created, - data.Id, - notificationId, - data.LiveMode, - data.Request); - - var details = data.Data.Object; - var created = DateTimeOffset.FromUnixTimeMilliseconds( - details.Value(StripeConstants.CreatedPropertyName)); - _logger.LogInformation( - 2, - "Event detail created at '{DetailsCreated}' and contains {PropertyCount} properties, including " + - "Account '{Account}', Id '{DetailsId}', Live mode '{DetailsLiveMode}', and Name '{Name}'.", - created, - details.Count, - details.Value("account"), - details.Value("id"), - details.Value(StripeConstants.LiveModePropertyName), - details.Value("name")); - - return Ok(); - } - } -} diff --git a/samples/StripeCoreReceiver/Program.cs b/samples/StripeCoreReceiver/Program.cs deleted file mode 100644 index f32571b..0000000 --- a/samples/StripeCoreReceiver/Program.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; - -namespace StripeCoreReceiver -{ - public class Program - { - public static void Main(string[] args) - { - BuildWebHost(args).Run(); - } - - public static IWebHost BuildWebHost(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup() - .Build(); - } -} diff --git a/samples/StripeCoreReceiver/Startup.cs b/samples/StripeCoreReceiver/Startup.cs deleted file mode 100644 index 1673218..0000000 --- a/samples/StripeCoreReceiver/Startup.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; - -namespace StripeCoreReceiver -{ - public class Startup - { - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) - { - services - .AddMvcCore() - .AddStripeWebHooks(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env) - { - app.UseMvc(); - } - } -} diff --git a/samples/StripeCoreReceiver/StripeCoreReceiver.csproj b/samples/StripeCoreReceiver/StripeCoreReceiver.csproj deleted file mode 100644 index 4ef05de..0000000 --- a/samples/StripeCoreReceiver/StripeCoreReceiver.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - $(Configurations);CodeAnalysis - netcoreapp2.0 - - - - - - - - diff --git a/samples/StripeCoreReceiver/appsettings.json b/samples/StripeCoreReceiver/appsettings.json deleted file mode 100644 index e83460e..0000000 --- a/samples/StripeCoreReceiver/appsettings.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "Logging": { - "IncludeScopes": false, - "LogLevel": { - "Default": "Warning" - }, - "Console": { - "LogLevel": { - "StripeCoreReceiver": "Information", - "Default": "Warning", - "Microsoft": "Information" - } - } - } -} \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props deleted file mode 100644 index 9df186b..0000000 --- a/src/Directory.Build.props +++ /dev/null @@ -1,22 +0,0 @@ - - - <_ImportParentFile>false - <_ImportParentFile Condition="$(MSBuildProjectName.StartsWith( 'Microsoft.AspNetCore.' ))">true - - - - - - $(DefineConstants);ASPNETWEBHOOKS - true - Microsoft.AspNetCore.WebHooks - netstandard2.0 - - - - - <_Parameter1>Serviceable - <_Parameter2>True - - - diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/AzureAlertCondition.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/AzureAlertCondition.cs deleted file mode 100644 index edcccb7..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/AzureAlertCondition.cs +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Newtonsoft.Json; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Provides information about the condition under which the WebHook notification was sent from Azure Alert Service. - /// - public class AzureAlertCondition - { - /// - /// Gets or sets the name of the metric that defines what the rule monitors. - /// - [JsonProperty("metricName")] - public string MetricName { get; set; } - - /// - /// Gets or sets the units allowed in the metric, e.g. 'Bytes' and 'Percent'. - /// See 'https://msdn.microsoft.com/en-us/library/microsoft.azure.insights.models.unit.aspx' - /// for details. - /// - [JsonProperty("metricUnit")] - public string MetricUnit { get; set; } - - /// - /// Gets or sets the actual value of the metric that caused the event. - /// - [JsonProperty("metricValue")] - public string MetricValue { get; set; } - - /// - /// Gets or sets the threshold value that activates the event. - /// - [JsonProperty("threshold")] - public string Threshold { get; set; } - - /// - /// Gets or sets the period of time that is used to monitor alert activity based on - /// the threshold. The value is between 5 minutes and 1 day. - /// - [JsonProperty("windowSize")] - public string WindowSize { get; set; } - - /// - /// Gets or sets how the data is collection, e.g. 'Average' and 'Last'. - /// See 'https://msdn.microsoft.com/en-us/library/microsoft.azure.insights.models.aggregationtype.aspx' for details. - /// - [JsonProperty("timeAggregation")] - public string TimeAggregation { get; set; } - - /// - /// Gets or sets the operator used to compare the data and the threshold. - /// - [JsonProperty("operator")] - public string Operator { get; set; } - - /// - /// Gets or sets details of an Availability (Web Test) failure. - /// - /// Set in Availability (Web Test) alerts but not Metric alerts. - [JsonProperty("failureDetails")] - public string FailureDetails { get; set; } - - /// - /// Gets or sets the name of an Availability (Web Test) alert. - /// - /// Set in Availability (Web Test) alerts but not Metric alerts. - [JsonProperty("webTestName")] - public string WebTestName { get; set; } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/AzureAlertConstants.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/AzureAlertConstants.cs deleted file mode 100644 index fd4f11a..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/AzureAlertConstants.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Well-known names used in Azure Alert receivers and handlers. - /// - public static class AzureAlertConstants - { - /// - /// Gets the JSON path of the property in an Azure Alert WebHook request body containing the Azure Alert event - /// name. Matches the Application Insights rule name. - /// - public static string EventBodyPropertyPath => "$['context']['name']"; - - /// - /// Gets the name of the Azure Alert WebHook receiver. - /// - public static string ReceiverName => "azurealert"; - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/AzureAlertContext.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/AzureAlertContext.cs deleted file mode 100644 index 8c1ef49..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/AzureAlertContext.cs +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Newtonsoft.Json; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Provides context information for a WebHook notification sent from Azure Alert Service. - /// - public class AzureAlertContext - { - /// - /// Gets or sets the unique ID for this alert. - /// - [JsonProperty("id", Required = Required.Always)] - public string Id { get; set; } - - /// - /// Gets or sets the name of the alert. - /// - [JsonProperty("name", Required = Required.Always)] - public string Name { get; set; } - - /// - /// Gets or sets the description of the alert. - /// - [JsonProperty("description", Required = Required.Always)] - public string Description { get; set; } - - /// - /// Gets or sets the condition type, e.g. 'Metric' or 'Event'. - /// - [JsonProperty("conditionType", Required = Required.Always)] - public string ConditionType { get; set; } - - /// - /// Gets or sets the Azure subscription ID. - /// - [JsonProperty("subscriptionId", Required = Required.Always)] - public string SubscriptionId { get; set; } - - /// - /// Gets or sets the time at which the alert was triggered. The alert is triggered as soon as - /// the metric is read from the diagnostics storage. - /// - [JsonProperty("timestamp", Required = Required.Always)] - public DateTime Timestamp { get; set; } - - /// - /// Gets or sets information about the condition causing the event. - /// - [JsonProperty("condition", Required = Required.Always)] - public AzureAlertCondition Condition { get; set; } - - /// - /// Gets or sets the resource group name of the impacted resource causing the alert. - /// - [JsonProperty("resourceGroupName", Required = Required.Always)] - public string ResourceGroupName { get; set; } - - /// - /// Gets or sets the name of the resource causing the alert. - /// - [JsonProperty("resourceName", Required = Required.Always)] - public string ResourceName { get; set; } - - /// - /// Gets or sets the type of the impacted resource. - /// - [JsonProperty("resourceType", Required = Required.Always)] - public string ResourceType { get; set; } - - /// - /// Gets or sets the ID of the resource. - /// - [JsonProperty("resourceId", Required = Required.Always)] - public string ResourceId { get; set; } - - /// - /// Gets or sets the geographic location of the resource. - /// - /// Set in Metric alerts but not Availability (Web Test) alerts. - [JsonProperty("resourceRegion")] - public string ResourceRegion { get; set; } - - /// - /// Gets or sets a direct link to the resource summary page on the Azure portal. - /// - [JsonProperty("portalLink", Required = Required.Always)] - public string PortalLink { get; set; } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/AzureAlertNotification.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/AzureAlertNotification.cs deleted file mode 100644 index 8b30352..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/AzureAlertNotification.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Contains information sent in a WebHook notification from Azure Alert Service. - /// - public class AzureAlertNotification - { - private readonly IDictionary _properties = new Dictionary(); - - /// - /// Gets or sets the kind of alert. Azure automatically sends activated and resolved alerts for the condition sets. - /// Examples of values include 'Activated' and 'Resolved'. - /// - [JsonProperty("status", Required = Required.Always)] - public string Status { get; set; } - - /// - /// Gets or sets context information for this alert. - /// - [JsonProperty("context", Required = Required.Always)] - public AzureAlertContext Context { get; set; } - - /// - /// Gets a collection of additional properties for this alert. - /// - [JsonProperty("properties")] - public IDictionary Properties - { - get { return _properties; } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/AzureAlertWebHookAttribute.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/AzureAlertWebHookAttribute.cs deleted file mode 100644 index 9b493b6..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/AzureAlertWebHookAttribute.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// - /// An indicating the associated action is an Azure Alert WebHook endpoint. - /// Specifies the optional . Also adds a - /// for the action. - /// - /// - /// The signature of the action should be: - /// - /// Task{IActionResult} ActionName(string id, string @event, TData data) - /// - /// or include the subset of parameters required. TData must be compatible with expected requests e.g. - /// or . - /// - /// - /// An example Azure Alert WebHook URI is - /// 'https://{host}/api/webhooks/incoming/azurealert/{id}?code=83699ec7c1d794c0c780e49a5c72972590571fd8'. - /// See - /// - /// for additional details about Azure Alert WebHook requests. - /// - /// - /// - /// - /// If the application enables CORS in general (see the Microsoft.AspNetCore.Cors package), apply - /// DisableCorsAttribute to this action. If the application depends on the - /// Microsoft.AspNetCore.Mvc.ViewFeatures package, apply IgnoreAntiforgeryTokenAttribute to this - /// action. - /// - /// - /// should be used at most once per in a - /// WebHook application. - /// - /// - public class AzureAlertWebHookAttribute : WebHookAttribute - { - /// - /// Instantiates a new indicating the associated action is an Azure - /// Alert WebHook endpoint. - /// - public AzureAlertWebHookAttribute() - : base(AzureAlertConstants.ReceiverName) - { - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/Extensions/AzureAlertMvcBuilderExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/Extensions/AzureAlertMvcBuilderExtensions.cs deleted file mode 100644 index 4418cdc..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/Extensions/AzureAlertMvcBuilderExtensions.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using Microsoft.AspNetCore.WebHooks.Internal; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up Azure Alert WebHooks in an . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class AzureAlertMvcBuilderExtensions - { - /// - /// - /// Add Azure Alert WebHook configuration and services to the specified . See - /// - /// for additional details about Azure Alert WebHook requests. - /// - /// - /// The 'WebHooks:AzureAlert:SecretKey:default' configuration value contains the secret key for Azure - /// Alert WebHook URIs of the form 'https://{host}/api/webhooks/incoming/azurealert?code={secret key}'. - /// 'WebHooks:AzureAlert:SecretKey:{id}' configuration values contain secret keys for - /// Azure Alert WebHook URIs of the form - /// 'https://{host}/api/webhooks/incoming/azurealert/{id}?code={secret key}'. - /// - /// - /// The to configure. - /// The . - public static IMvcBuilder AddAzureAlertWebHooks(this IMvcBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - AzureAlertServiceCollectionSetup.AddAzureAlertServices(builder.Services); - - return builder.AddWebHooks(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/Extensions/AzureAlertMvcCoreBuilderExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/Extensions/AzureAlertMvcCoreBuilderExtensions.cs deleted file mode 100644 index 242934c..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/Extensions/AzureAlertMvcCoreBuilderExtensions.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using Microsoft.AspNetCore.WebHooks.Internal; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up Azure Alert WebHooks in an . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class AzureAlertMvcCoreBuilderExtensions - { - /// - /// - /// Add Azure Alert WebHook configuration and services to the specified . See - /// - /// for additional details about Azure Alert WebHook requests. - /// - /// - /// The 'WebHooks:AzureAlert:SecretKey:default' configuration value contains the secret key for Azure - /// Alert WebHook URIs of the form 'https://{host}/api/webhooks/incoming/azurealert?code={secret key}'. - /// 'WebHooks:AzureAlert:SecretKey:{id}' configuration values contain secret keys for - /// Azure Alert WebHook URIs of the form - /// 'https://{host}/api/webhooks/incoming/azurealert/{id}?code={secret key}'. - /// - /// - /// The to configure. - /// The . - public static IMvcCoreBuilder AddAzureAlertWebHooks(this IMvcCoreBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - AzureAlertServiceCollectionSetup.AddAzureAlertServices(builder.Services); - - return builder - .AddJsonFormatters() - .AddWebHooks(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/Internal/AzureAlertServiceCollectionSetup.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/Internal/AzureAlertServiceCollectionSetup.cs deleted file mode 100644 index 54e1982..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/Internal/AzureAlertServiceCollectionSetup.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; - -namespace Microsoft.AspNetCore.WebHooks.Internal -{ - /// - /// Methods to add services for the Azure Alert receiver. - /// - public static class AzureAlertServiceCollectionSetup - { - /// - /// Add services for the Azure Alert receiver. - /// - /// The to update. - public static void AddAzureAlertServices(IServiceCollection services) - { - if (services == null) - { - throw new ArgumentNullException(nameof(services)); - } - - services.TryAddEnumerable(ServiceDescriptor.Singleton()); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/Metadata/AzureAlertMetadata.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/Metadata/AzureAlertMetadata.cs deleted file mode 100644 index d6029db..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/Metadata/AzureAlertMetadata.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// An service containing metadata about the Azure Alert receiver. - /// - public class AzureAlertMetadata : - WebHookMetadata, - IWebHookBodyTypeMetadataService, - IWebHookEventFromBodyMetadata, - IWebHookVerifyCodeMetadata - { - /// - /// Instantiates a new instance. - /// - public AzureAlertMetadata() - : base(AzureAlertConstants.ReceiverName) - { - } - - // IWebHookBodyTypeMetadataService... - - /// - public WebHookBodyType BodyType => WebHookBodyType.Json; - - // IWebHookEventFromBodyMetadata... - - /// - public bool AllowMissing => false; - - /// - public string BodyPropertyPath => AzureAlertConstants.EventBodyPropertyPath; - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert.csproj b/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert.csproj deleted file mode 100644 index f73e60e..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert/Microsoft.AspNetCore.WebHooks.Receivers.AzureAlert.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - $(Configurations);CodeAnalysis - ASP.NET Core Azure Alert WebHooks infrastructure. Contains the AzureAlertWebHookAttribute class and AddAzureAlertWebHooks method. - aspnetcore;webhook;receiver;azurealert - - - - - - - diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketAuthor.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketAuthor.cs deleted file mode 100644 index 4117470..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketAuthor.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Newtonsoft.Json; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Contains information about a Bitbucket author. - /// - public class BitbucketAuthor - { - /// - /// Gets or sets the Bitbucket user information for this author. - /// - [JsonProperty("user")] - public BitbucketUser User { get; set; } - - /// - /// Gets or sets the raw author in the form of a name and email alias. - /// - [JsonProperty("raw")] - public string Raw { get; set; } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketConstants.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketConstants.cs deleted file mode 100644 index e556747..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketConstants.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Well-known names used in Bitbucket receivers and handlers. - /// - public static class BitbucketConstants - { - /// - /// Gets the name of the header containing the Bitbucket event name e.g. repo:push or - /// issue:created. - /// - public static string EventHeaderName => "X-Event-Key"; - - /// - /// Gets the name of the Bitbucket WebHook receiver. - /// - public static string ReceiverName => "bitbucket"; - - /// - /// Gets the name of the header containing the Bitbucket WebHook UUID. - /// - public static string WebHookIdHeaderName => "X-Hook-UUID"; - - /// - /// Gets the name of one parameter bound to the header. - /// - public static string WebHookIdParameterName1 => "webHookid"; - - /// - /// Gets the name of another parameter bound to the header. - /// - public static string WebHookIdParameterName2 => "webHook_id"; - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketLink.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketLink.cs deleted file mode 100644 index 7b001cd..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketLink.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Newtonsoft.Json; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Contains information about a link in Bitbucket. - /// - public class BitbucketLink - { - /// - /// Gets or sets the URI of the link. - /// - [JsonProperty("href")] - public string Reference { get; set; } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketParent.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketParent.cs deleted file mode 100644 index 9ba1a45..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketParent.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Contains information about a parent commit in Bitbucket. - /// - public class BitbucketParent - { - private readonly IDictionary _links = new Dictionary(); - - /// - /// Gets or sets the hash of the parent commit. - /// - [JsonProperty("hash")] - public string Hash { get; set; } - - /// - /// The type of operation on the repository, e.g. 'commit'. - /// - [JsonProperty("type")] - public string Operation { get; set; } - - /// - /// Gets the collection of instances and their link relationships. The - /// key is the link relationship and the value is the actual link. - /// - [JsonProperty("links")] - public IDictionary Links - { - get { return _links; } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketRepository.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketRepository.cs deleted file mode 100644 index b45e2eb..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketRepository.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Contains information about a Bitbucket repository. - /// - public class BitbucketRepository - { - private readonly IDictionary _links = new Dictionary(); - - /// - /// Gets or sets a unique ID for this repository. - /// - [JsonProperty("uuid")] - public string RepositoryId { get; set; } - - /// - /// Gets or sets the full name of the repository, e.g. 'someuser/myrepo'. - /// - [JsonProperty("full_name")] - public string FullName { get; set; } - - /// - /// Gets or sets the name of the repository, e.g. 'myrepo'. - /// - [JsonProperty("name")] - public string Name { get; set; } - - /// - /// Gets or sets a value indicating with the repository is private or not. - /// - [JsonProperty("is_private")] - public bool IsPrivate { get; set; } - - /// - /// Gets the collection of instances and their link relationships. The - /// key is the link relationship and the value is the actual link. - /// - [JsonProperty("links")] - public IDictionary Links - { - get { return _links; } - } - - /// - /// Gets or sets the kind of this element, e.g. 'repository'. - /// - [JsonProperty("type")] - public string ItemType { get; set; } - - /// - /// Gets or sets the type of repository, e.g. 'hg'. - /// - [JsonProperty("scm")] - public string RepositoryType { get; set; } - - /// - /// Gets or sets the Bitbucket user information for owner of the repository. - /// - public BitbucketUser Owner { get; set; } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketTarget.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketTarget.cs deleted file mode 100644 index f4e8248..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketTarget.cs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using Newtonsoft.Json; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Contains details about the most recent operation to a Bitbucket repository after a push. - /// - public class BitbucketTarget - { - private readonly Collection _parents = new Collection(); - private readonly IDictionary _links = new Dictionary(); - - /// - /// Gets or sets the email alias for this author. - /// - [JsonProperty("message")] - public string Message { get; set; } - - /// - /// The type of operation on the repository, e.g. 'commit'. - /// - [JsonProperty("type")] - public string Operation { get; set; } - - /// - /// Gets the collection of instances and their link relationships. The - /// key is the link relationship and the value is the actual link. - /// - [JsonProperty("links")] - public IDictionary Links - { - get { return _links; } - } - - /// - /// Gets or sets the hash of the commit - /// - [JsonProperty("hash")] - public string Hash { get; set; } - - /// - /// Gets the collection of instances for this target. - /// - [JsonProperty("parents")] - public Collection Parents - { - get { return _parents; } - } - - /// - /// Gets or sets the for this target. - /// - [JsonProperty("author")] - public BitbucketAuthor Author { get; set; } - - /// - /// Gets or set the UTC time of this target. - /// - [JsonProperty("date")] - public DateTime Date { get; set; } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketUser.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketUser.cs deleted file mode 100644 index a7bce68..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketUser.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Contains information about a user in Bitbucket. - /// - public class BitbucketUser - { - private readonly IDictionary _links = new Dictionary(); - - /// - /// Gets or sets a unique ID for this user. - /// - [JsonProperty("uuid")] - public string UserId { get; set; } - - /// - /// Gets or sets the type of the user. - /// - [JsonProperty("type")] - public string UserType { get; set; } - - /// - /// Gets or sets the the first and last name of the user. - /// - [JsonProperty("display_name")] - public string DisplayName { get; set; } - - /// - /// Gets or sets the user name for this user. - /// - [JsonProperty("username")] - public string UserName { get; set; } - - /// - /// Gets the collection of instances and their link relationships. The - /// key is the link relationship and the value is the actual link. - /// - [JsonProperty("links")] - public IDictionary Links - { - get { return _links; } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketWebHookAttribute.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketWebHookAttribute.cs deleted file mode 100644 index c0d0c04..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/BitbucketWebHookAttribute.cs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.AspNetCore.WebHooks.Properties; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// - /// An indicating the associated action is a Bitbucket WebHook endpoint. - /// Specifies the optional and . Also adds a - /// for the action. - /// - /// - /// The signature of the action should be: - /// - /// Task{IActionResult} ActionName(string id, string @event, string webHookId, TData data) - /// - /// or include the subset of parameters required. TData must be compatible with expected requests e.g. - /// . - /// - /// - /// An example Bitbucket WebHook URI is - /// 'https://{host}/api/webhooks/incoming/bitbucket/{id}?code=83699ec7c1d794c0c780e49a5c72972590571fd8'. - /// See for additional - /// details about Bitbucket WebHook requests. - /// - /// - /// - /// - /// If the application enables CORS in general (see the Microsoft.AspNetCore.Cors package), apply - /// DisableCorsAttribute to this action. If the application depends on the - /// Microsoft.AspNetCore.Mvc.ViewFeatures package, apply IgnoreAntiforgeryTokenAttribute to this - /// action. - /// - /// - /// should be used at most once per and - /// in a WebHook application. - /// - /// - public class BitbucketWebHookAttribute : WebHookAttribute, IWebHookEventSelectorMetadata - { - private string _eventName; - - /// - /// Instantiates a new indicating the associated action is a Bitbucket - /// WebHook endpoint. - /// - public BitbucketWebHookAttribute() - : base(BitbucketConstants.ReceiverName) - { - } - - /// - /// Gets or sets the name of the event the associated controller action accepts. - /// - /// Default value is , indicating this action accepts all events. - public string EventName - { - get - { - return _eventName; - } - set - { - if (string.IsNullOrEmpty(value)) - { - throw new ArgumentException(Resources.General_ArgumentCannotBeNullOrEmpty, nameof(value)); - } - - _eventName = value; - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Extensions/BitbucketMvcBuilderExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Extensions/BitbucketMvcBuilderExtensions.cs deleted file mode 100644 index 18c9de0..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Extensions/BitbucketMvcBuilderExtensions.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using Microsoft.AspNetCore.WebHooks.Internal; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up Bitbucket WebHooks in an . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class BitbucketMvcBuilderExtensions - { - /// - /// - /// Add Bitbucket WebHook configuration and services to the specified . See - /// for additional - /// details about Bitbucket WebHook requests. - /// - /// - /// The 'WebHooks:Bitbucket:SecretKey:default' configuration value contains the secret key for Bitbucket - /// WebHook URIs of the form 'https://{host}/api/webhooks/incoming/bitbucket?code={secret key}'. - /// 'WebHooks:Bitbucket:SecretKey:{id}' configuration values contain secret keys for Bitbucket WebHook - /// URIs of the form 'https://{host}/api/webhooks/incoming/bitbucket/{id}?code={secret key}'. - /// - /// - /// The to configure. - /// The . - public static IMvcBuilder AddBitbucketWebHooks(this IMvcBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - BitbucketServiceCollectionSetup.AddBitbucketServices(builder.Services); - - return builder.AddWebHooks(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Extensions/BitbucketMvcCoreBuilderExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Extensions/BitbucketMvcCoreBuilderExtensions.cs deleted file mode 100644 index c9d48e8..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Extensions/BitbucketMvcCoreBuilderExtensions.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using Microsoft.AspNetCore.WebHooks.Internal; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up Bitbucket WebHooks in an . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class BitbucketMvcCoreBuilderExtensions - { - /// - /// - /// Add Bitbucket WebHook configuration and services to the specified . See - /// for additional - /// details about Bitbucket WebHook requests. - /// - /// - /// The 'WebHooks:Bitbucket:SecretKey:default' configuration value contains the secret key for Bitbucket - /// WebHook URIs of the form 'https://{host}/api/webhooks/incoming/bitbucket?code={secret key}'. - /// 'WebHooks:Bitbucket:SecretKey:{id}' configuration values contain secret keys for Bitbucket WebHook - /// URIs of the form 'https://{host}/api/webhooks/incoming/bitbucket/{id}?code={secret key}'. - /// - /// - /// The to configure. - /// The . - public static IMvcCoreBuilder AddBitbucketWebHooks(this IMvcCoreBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - BitbucketServiceCollectionSetup.AddBitbucketServices(builder.Services); - - return builder - .AddJsonFormatters() - .AddWebHooks(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Internal/BitbucketServiceCollectionSetup.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Internal/BitbucketServiceCollectionSetup.cs deleted file mode 100644 index ec33fd4..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Internal/BitbucketServiceCollectionSetup.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; - -namespace Microsoft.AspNetCore.WebHooks.Internal -{ - /// - /// Methods to add services for the Bitbucket receiver. - /// - public static class BitbucketServiceCollectionSetup - { - /// - /// Add services for the Bitbucket receiver. - /// - /// The to update. - public static void AddBitbucketServices(IServiceCollection services) - { - if (services == null) - { - throw new ArgumentNullException(nameof(services)); - } - - services.TryAddEnumerable(ServiceDescriptor.Singleton()); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Metadata/BitbucketMetadata.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Metadata/BitbucketMetadata.cs deleted file mode 100644 index 600fd4e..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Metadata/BitbucketMetadata.cs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// An service containing metadata about the Bitbucket receiver. - /// - public class BitbucketMetadata : - WebHookMetadata, - IWebHookBindingMetadata, - IWebHookBodyTypeMetadataService, - IWebHookEventMetadata, - IWebHookVerifyCodeMetadata - { - /// - /// Instantiates a new instance. - /// - public BitbucketMetadata() - : base(BitbucketConstants.ReceiverName) - { - } - - // IWebHookBindingMetadata... - - /// - public IReadOnlyList Parameters { get; } = new WebHookParameter[] - { - new WebHookParameter( - BitbucketConstants.WebHookIdParameterName1, - WebHookParameterType.Header, - BitbucketConstants.WebHookIdHeaderName, - isRequired: true), - new WebHookParameter( - BitbucketConstants.WebHookIdParameterName2, - WebHookParameterType.Header, - BitbucketConstants.WebHookIdHeaderName, - isRequired: true), - }; - - // IWebHookBodyTypeMetadataService... - - /// - public WebHookBodyType BodyType => WebHookBodyType.Json; - - // IWebHookEventMetadata... - - /// - public string ConstantValue => null; - - /// - public string HeaderName => BitbucketConstants.EventHeaderName; - - /// - public string QueryParameterName => null; - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket.csproj b/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket.csproj deleted file mode 100644 index 788cf25..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - $(Configurations);CodeAnalysis - ASP.NET Core Bitbucket WebHooks infrastructure. Contains the BitbucketWebHookAttribute class and AddBitbucketWebHooks method. - aspnetcore;webhook;receiver;bitbucket - - - - - - - diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Properties/Resources.Designer.cs deleted file mode 100644 index ffe2cbc..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Properties/Resources.Designer.cs +++ /dev/null @@ -1,72 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Microsoft.AspNetCore.WebHooks.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.AspNetCore.WebHooks.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to Value cannot be null or empty.. - /// - internal static string General_ArgumentCannotBeNullOrEmpty { - get { - return ResourceManager.GetString("General_ArgumentCannotBeNullOrEmpty", resourceCulture); - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Properties/Resources.resx b/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Properties/Resources.resx deleted file mode 100644 index fd709f6..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.BitBucket/Properties/Resources.resx +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Value cannot be null or empty. - - \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/DropboxConstants.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/DropboxConstants.cs deleted file mode 100644 index 3bbef98..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/DropboxConstants.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Well-known names and values used in Dropbox receivers and handlers. - /// - public static class DropboxConstants - { - /// - /// Gets the name of a query parameter containing a value to include in the response to an HTTP GET request. - /// - public static string ChallengeQueryParameterName => "challenge"; - - /// - /// Gets the only supported event name for this receiver. This value may be model bound but cannot be used in - /// action selection. - /// - public static string EventName => "change"; - - /// - /// Gets the name of the Dropbox WebHook receiver. - /// - public static string ReceiverName => "dropbox"; - - /// - /// Gets the minimum length of the secret key configured for this receiver. Used to confirm the secret key is - /// property configured before responding to an HTTP GET request. - /// - public static int SecretKeyMinLength => 15; - - /// - /// Gets the maximum length of the secret key configured for this receiver. Used to confirm the secret key is - /// property configured before responding to an HTTP GET request. - /// - public static int SecretKeyMaxLength => 128; - - /// - /// Gets the name of the HTTP header that contains the (hex-encoded) signature of the request. - /// - public static string SignatureHeaderName => "X-Dropbox-Signature"; - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/DropboxWebHookAttribute.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/DropboxWebHookAttribute.cs deleted file mode 100644 index 26f3adc..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/DropboxWebHookAttribute.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// - /// An indicating the associated action is a Dropbox WebHook endpoint. Specifies the - /// optional . Also adds a for - /// the action. - /// - /// - /// The signature of the action should be: - /// - /// Task{IActionResult} ActionName(string id, string @event, TData data) - /// - /// or include the subset of parameters required. @event will always contain the value "change". - /// TData must be compatible with expected requests e.g. . - /// - /// - /// An example Dropbox WebHook URI is 'https://{host}/api/webhooks/incoming/dropbox/{id}'. See - /// for additional details about Dropbox WebHook - /// requests. - /// - /// - /// - /// - /// If the application enables CORS in general (see the Microsoft.AspNetCore.Cors package), apply - /// DisableCorsAttribute to this action. If the application depends on the - /// Microsoft.AspNetCore.Mvc.ViewFeatures package, apply IgnoreAntiforgeryTokenAttribute to this - /// action. - /// - /// - /// should be used at most once per in a - /// WebHook application. - /// - /// - public class DropboxWebHookAttribute : WebHookAttribute - { - /// - /// Instantiates a new indicating the associated action is a Dropbox - /// WebHook endpoint. - /// - public DropboxWebHookAttribute() - : base(DropboxConstants.ReceiverName) - { - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/Extensions/DropboxMvcBuilderExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/Extensions/DropboxMvcBuilderExtensions.cs deleted file mode 100644 index baf11f8..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/Extensions/DropboxMvcBuilderExtensions.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using Microsoft.AspNetCore.WebHooks.Internal; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up Dropbox WebHooks in an . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class DropboxMvcBuilderExtensions - { - /// - /// - /// Add Dropbox WebHook configuration and services to the specified . See - /// for additional details about Dropbox WebHook - /// requests. - /// - /// - /// The 'WebHooks:Dropbox:SecretKey:default' configuration value contains the secret key for Dropbox - /// WebHook URIs of the form 'https://{host}/api/webhooks/incoming/dropbox'. - /// 'WebHooks:Dropbox:SecretKey:{id}' configuration values contain secret keys for Dropbox WebHook URIs - /// of the form 'https://{host}/api/webhooks/incoming/dropbox/{id}'. - /// - /// - /// The to configure. - /// The . - public static IMvcBuilder AddDropboxWebHooks(this IMvcBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - DropboxServiceCollectionSetup.AddDropboxServices(builder.Services); - - return builder.AddWebHooks(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/Extensions/DropboxMvcCoreBuilderExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/Extensions/DropboxMvcCoreBuilderExtensions.cs deleted file mode 100644 index 450877b..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/Extensions/DropboxMvcCoreBuilderExtensions.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using Microsoft.AspNetCore.WebHooks.Internal; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up Dropbox WebHooks in an . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class DropboxMvcCoreBuilderExtensions - { - /// - /// - /// Add Dropbox WebHook configuration and services to the specified . See - /// for additional details about Dropbox WebHook - /// requests. - /// - /// - /// The 'WebHooks:Dropbox:SecretKey:default' configuration value contains the secret key for Dropbox - /// WebHook URIs of the form 'https://{host}/api/webhooks/incoming/dropbox'. - /// 'WebHooks:Dropbox:SecretKey:{id}' configuration values contain secret keys for Dropbox WebHook URIs - /// of the form 'https://{host}/api/webhooks/incoming/dropbox/{id}'. - /// - /// - /// The to configure. - /// The . - public static IMvcCoreBuilder AddDropboxWebHooks(this IMvcCoreBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - DropboxServiceCollectionSetup.AddDropboxServices(builder.Services); - - return builder - .AddJsonFormatters() - .AddWebHooks(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/Filters/DropboxVerifySignatureFilter.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/Filters/DropboxVerifySignatureFilter.cs deleted file mode 100644 index 433b2f9..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/Filters/DropboxVerifySignatureFilter.cs +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Text; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.AspNetCore.Routing; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; - -namespace Microsoft.AspNetCore.WebHooks.Filters -{ - /// - /// An that verifies the Dropbox signature header. Confirms the header exists, - /// reads Body bytes, and compares the hashes. - /// - public class DropboxVerifySignatureFilter : WebHookVerifySignatureFilter, IAsyncResourceFilter - { - /// - /// Instantiates a new instance. - /// - /// - /// The used to initialize . - /// - /// - /// The used to initialize - /// . - /// - /// - /// The used to initialize . - /// - public DropboxVerifySignatureFilter( - IConfiguration configuration, - IHostingEnvironment hostingEnvironment, - ILoggerFactory loggerFactory) - : base(configuration, hostingEnvironment, loggerFactory) - { - } - - /// - public override string ReceiverName => DropboxConstants.ReceiverName; - - /// - public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - if (next == null) - { - throw new ArgumentNullException(nameof(next)); - } - - var routeData = context.RouteData; - var request = context.HttpContext.Request; - if (routeData.TryGetWebHookReceiverName(out var receiverName) && - IsApplicable(receiverName) && - HttpMethods.IsPost(request.Method)) - { - // 1. Confirm a secure connection. - var errorResult = EnsureSecureConnection(ReceiverName, context.HttpContext.Request); - if (errorResult != null) - { - context.Result = errorResult; - return; - } - - // 2. Get the expected hash from the signature header. - var header = GetRequestHeader(request, DropboxConstants.SignatureHeaderName, out errorResult); - if (errorResult != null) - { - context.Result = errorResult; - return; - } - - var expectedHash = GetDecodedHash(header, DropboxConstants.SignatureHeaderName, out errorResult); - if (errorResult != null) - { - context.Result = errorResult; - return; - } - - // 3. Get the configured secret key. - var secretKey = GetSecretKey( - ReceiverName, - routeData, - DropboxConstants.SecretKeyMinLength, - DropboxConstants.SecretKeyMaxLength); - if (secretKey == null) - { - context.Result = new NotFoundResult(); - return; - } - - var secret = Encoding.UTF8.GetBytes(secretKey); - - // 4. Get the actual hash of the request body. - var actualHash = await GetRequestBodyHash_SHA256(request, secret); - - // 5. Verify that the actual hash matches the expected hash. - if (!SecretEqual(expectedHash, actualHash)) - { - // Log about the issue and short-circuit remainder of the pipeline. - errorResult = CreateBadSignatureResult(receiverName, DropboxConstants.SignatureHeaderName); - - context.Result = errorResult; - return; - } - } - - await next(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/Internal/DropboxServiceCollectionSetup.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/Internal/DropboxServiceCollectionSetup.cs deleted file mode 100644 index 813fff5..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/Internal/DropboxServiceCollectionSetup.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.WebHooks.Filters; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Options; - -namespace Microsoft.AspNetCore.WebHooks.Internal -{ - /// - /// Methods to add services for the Dropbox receiver. - /// - public static class DropboxServiceCollectionSetup - { - /// - /// Add services for the Dropbox receiver. - /// - /// The to update. - public static void AddDropboxServices(IServiceCollection services) - { - if (services == null) - { - throw new ArgumentNullException(nameof(services)); - } - - services.TryAddEnumerable(ServiceDescriptor.Transient, MvcOptionsSetup>()); - services.TryAddEnumerable(ServiceDescriptor.Singleton()); - - services.TryAddSingleton(); - } - - private class MvcOptionsSetup : IConfigureOptions - { - /// - public void Configure(MvcOptions options) - { - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } - - options.Filters.AddService(WebHookSecurityFilter.Order); - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/Metadata/DropboxMetadata.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/Metadata/DropboxMetadata.cs deleted file mode 100644 index be47b8f..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/Metadata/DropboxMetadata.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// An service containing metadata about the Dropbox receiver. - /// - public class DropboxMetadata : - WebHookMetadata, - IWebHookBodyTypeMetadataService, - IWebHookEventMetadata, - IWebHookGetRequestMetadata - { - /// - /// Instantiates a new instance. - /// - public DropboxMetadata() - : base(DropboxConstants.ReceiverName) - { - } - - // IWebHookBodyTypeMetadataService... - - /// - public WebHookBodyType BodyType => WebHookBodyType.Json; - - // IWebHookEventMetadata... - - /// - public string ConstantValue => DropboxConstants.EventName; - - /// - public string HeaderName => null; - - /// - public string QueryParameterName => null; - - // IWebHookGetRequestMetadata... - - /// - public string ChallengeQueryParameterName => DropboxConstants.ChallengeQueryParameterName; - - /// - public int SecretKeyMinLength => DropboxConstants.SecretKeyMinLength; - - /// - public int SecretKeyMaxLength => DropboxConstants.SecretKeyMaxLength; - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox.csproj b/src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox.csproj deleted file mode 100644 index ddbc2fe..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox/Microsoft.AspNetCore.WebHooks.Receivers.Dropbox.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - $(Configurations);CodeAnalysis - ASP.NET Core Dropbox WebHooks infrastructure. Contains the DropboxWebHookAttribute class and AddDropboxWebHooks method. - aspnetcore;webhook;receiver;dropbox - - - - - - - diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/DynamicsCRMConstants.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/DynamicsCRMConstants.cs deleted file mode 100644 index 601eaff..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/DynamicsCRMConstants.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Well-known names used in Dynamics CRM receivers and handlers. - /// - public static class DynamicsCRMConstants - { - /// - /// Gets the JSON path of the property in a Dynamics CRM WebHook request body containing the Dynamics CRM - /// event name. - /// - public static string EventBodyPropertyPath => "$.MessageName"; - - /// - /// Gets the name of the Dynamics CRM WebHook receiver. - /// - public static string ReceiverName => "dynamicscrm"; - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/DynamicsCRMWebHookAttribute.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/DynamicsCRMWebHookAttribute.cs deleted file mode 100644 index c9c452e..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/DynamicsCRMWebHookAttribute.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// - /// An indicating the associated action is a Dynamics CRM WebHook endpoint. - /// Specifies the optional . Also adds a - /// for the action. - /// - /// - /// The signature of the action should be: - /// - /// Task{IActionResult} ActionName(string id, string @event, TData data) - /// - /// or include the subset of parameters required. TData must be compatible with expected requests e.g. - /// . - /// - /// - /// An example Dynamics CRM WebHook URI is - /// 'https://{host}/api/webhooks/incoming/dynamicscrm/{id}?code=83699ec7c1d794c0c780e49a5c72972590571fd8'. - /// See for additional details about Dynamics CRM - /// WebHook requests. - /// - /// - /// - /// - /// If the application enables CORS in general (see the Microsoft.AspNetCore.Cors package), apply - /// DisableCorsAttribute to this action. If the application depends on the - /// Microsoft.AspNetCore.Mvc.ViewFeatures package, apply IgnoreAntiforgeryTokenAttribute to this - /// action. - /// - /// - /// should be used at most once per in - /// a WebHook application. - /// - /// - public class DynamicsCRMWebHookAttribute : WebHookAttribute - { - /// - /// Instantiates a new indicating the associated action is a Dynamics - /// CRM WebHook endpoint. - /// - public DynamicsCRMWebHookAttribute() - : base(DynamicsCRMConstants.ReceiverName) - { - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/Extensions/DynamicsCRMMvcBuilderExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/Extensions/DynamicsCRMMvcBuilderExtensions.cs deleted file mode 100644 index 9c4d2ab..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/Extensions/DynamicsCRMMvcBuilderExtensions.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using Microsoft.AspNetCore.WebHooks.Internal; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up Dynamics CRM WebHooks in an . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class DynamicsCRMMvcBuilderExtensions - { - /// - /// - /// Add Dynamics CRM WebHook configuration and services to the specified . See - /// for additional details about Dynamics CRM - /// WebHook requests. - /// - /// - /// The 'WebHooks:DynamicsCrm:SecretKey:default' configuration value contains the secret key for - /// Dynamics CRM WebHook URIs of the form - /// 'https://{host}/api/webhooks/incoming/dynamicscrm?code={secret key}'. - /// 'WebHooks:DynamicsCrm:SecretKey:{id}' configuration values contain secret keys for Dynamics CRM - /// WebHook URIs of the form 'https://{host}/api/webhooks/incoming/dynamicscrm/{id}?code={secret key}'. - /// - /// - /// The to configure. - /// The . - public static IMvcBuilder AddDynamicsCRMWebHooks(this IMvcBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - DynamicsCRMServiceCollectionSetup.AddDynamicsCRMServices(builder.Services); - - return builder.AddWebHooks(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/Extensions/DynamicsCRMMvcCoreBuilderExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/Extensions/DynamicsCRMMvcCoreBuilderExtensions.cs deleted file mode 100644 index daaba0a..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/Extensions/DynamicsCRMMvcCoreBuilderExtensions.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using Microsoft.AspNetCore.WebHooks.Internal; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up Dynamics CRM WebHooks in an . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class DynamicsCRMMvcCoreBuilderExtensions - { - /// - /// - /// Add Dynamics CRM WebHook configuration and services to the specified . See - /// for additional details about Dynamics CRM - /// WebHook requests. - /// - /// - /// The 'WebHooks:DynamicsCrm:SecretKey:default' configuration value contains the secret key for - /// Dynamics CRM WebHook URIs of the form - /// 'https://{host}/api/webhooks/incoming/dynamicscrm?code={secret key}'. - /// 'WebHooks:DynamicsCrm:SecretKey:{id}' configuration values contain secret keys for Dynamics CRM - /// WebHook URIs of the form 'https://{host}/api/webhooks/incoming/dynamicscrm/{id}?code={secret key}'. - /// - /// - /// The to configure. - /// The . - public static IMvcCoreBuilder AddDynamicsCRMWebHooks(this IMvcCoreBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - DynamicsCRMServiceCollectionSetup.AddDynamicsCRMServices(builder.Services); - - return builder - .AddJsonFormatters() - .AddWebHooks(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/Internal/DynamicsCRMServiceCollectionSetup.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/Internal/DynamicsCRMServiceCollectionSetup.cs deleted file mode 100644 index 795d0c3..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/Internal/DynamicsCRMServiceCollectionSetup.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; - -namespace Microsoft.AspNetCore.WebHooks.Internal -{ - /// - /// Methods to add services for the Dynamics CRM receiver. - /// - public static class DynamicsCRMServiceCollectionSetup - { - /// - /// Add services for the Dynamics CRM receiver. - /// - /// The to update. - public static void AddDynamicsCRMServices(IServiceCollection services) - { - if (services == null) - { - throw new ArgumentNullException(nameof(services)); - } - - services.TryAddEnumerable(ServiceDescriptor.Singleton()); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/Metadata/DynamicsCRMMetadata.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/Metadata/DynamicsCRMMetadata.cs deleted file mode 100644 index 60be6e1..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/Metadata/DynamicsCRMMetadata.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// An service containing metadata about the Dynamics CRM receiver. - /// - public class DynamicsCRMMetadata : - WebHookMetadata, - IWebHookBodyTypeMetadataService, - IWebHookEventFromBodyMetadata, - IWebHookVerifyCodeMetadata - { - /// - /// Instantiates a new instance. - /// - public DynamicsCRMMetadata() - : base(DynamicsCRMConstants.ReceiverName) - { - } - - // IWebHookBodyTypeMetadataService... - - /// - public WebHookBodyType BodyType => WebHookBodyType.Json; - - // IWebHookEventFromBodyMetadata... - - /// - public bool AllowMissing => true; - - /// - public string BodyPropertyPath => DynamicsCRMConstants.EventBodyPropertyPath; - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM.csproj b/src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM.csproj deleted file mode 100644 index 05bb6c2..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM/Microsoft.AspNetCore.WebHooks.Receivers.DynamicsCRM.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - $(Configurations);CodeAnalysis - ASP.NET Core Dynamics CRM WebHooks infrastructure. Contains the DynamicsCRMWebHookAttribute class and AddDynamicsCRMWebHooks method. - aspnetcore;webhook;receiver;dynamicscrm - - - - - - - diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Extensions/GitHubMvcBuilderExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Extensions/GitHubMvcBuilderExtensions.cs deleted file mode 100644 index 08dd788..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Extensions/GitHubMvcBuilderExtensions.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using Microsoft.AspNetCore.WebHooks.Internal; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up GitHub WebHooks in an . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class GitHubMvcBuilderExtensions - { - /// - /// - /// Add GitHub WebHook configuration and services to the specified . See - /// for additional details about GitHub WebHook requests. - /// - /// - /// The 'WebHooks:GitHub:SecretKey:default' configuration value contains the secret key for GitHub - /// WebHook URIs of the form 'https://{host}/api/webhooks/incoming/github'. - /// 'WebHooks:GitHub:SecretKey:{id}' configuration values contain secret keys for GitHub WebHook URIs of - /// the form 'https://{host}/api/webhooks/incoming/github/{id}'. - /// - /// - /// The to configure. - /// The . - public static IMvcBuilder AddGitHubWebHooks(this IMvcBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - GitHubServiceCollectionSetup.AddGitHubServices(builder.Services); - - return builder.AddWebHooks(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Extensions/GitHubMvcCoreBuilderExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Extensions/GitHubMvcCoreBuilderExtensions.cs deleted file mode 100644 index d6f2525..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Extensions/GitHubMvcCoreBuilderExtensions.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using Microsoft.AspNetCore.WebHooks.Internal; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up GitHub WebHooks in an . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class GitHubMvcCoreBuilderExtensions - { - /// - /// - /// Add GitHub WebHook configuration and services to the specified . See - /// for additional details about GitHub WebHook requests. - /// - /// - /// The 'WebHooks:GitHub:SecretKey:default' configuration value contains the secret key for GitHub - /// WebHook URIs of the form 'https://{host}/api/webhooks/incoming/github'. - /// 'WebHooks:GitHub:SecretKey:{id}' configuration values contain secret keys for GitHub WebHook URIs of - /// the form 'https://{host}/api/webhooks/incoming/github/{id}'. - /// - /// - /// The to configure. - /// The . - public static IMvcCoreBuilder AddGitHubWebHooks(this IMvcCoreBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - GitHubServiceCollectionSetup.AddGitHubServices(builder.Services); - - return builder - .AddJsonFormatters() - .AddWebHooks(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Filters/GitHubVerifySignatureFilter.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Filters/GitHubVerifySignatureFilter.cs deleted file mode 100644 index d99392b..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Filters/GitHubVerifySignatureFilter.cs +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Globalization; -using System.Text; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.WebHooks.Properties; -using Microsoft.AspNetCore.WebHooks.Utilities; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Primitives; - -namespace Microsoft.AspNetCore.WebHooks.Filters -{ - /// - /// An that verifies the GitHub signature header. Confirms the header exists, - /// reads Body bytes, and compares the hashes. - /// - public class GitHubVerifySignatureFilter : WebHookVerifySignatureFilter, IAsyncResourceFilter - { - // Character that appears between the key and value in the signature header. - private static readonly char[] PairSeparators = new[] { '=' }; - - /// - /// Instantiates a new instance. - /// - /// - /// The used to initialize . - /// - /// - /// The used to initialize - /// . - /// - /// - /// The used to initialize . - /// - public GitHubVerifySignatureFilter( - IConfiguration configuration, - IHostingEnvironment hostingEnvironment, - ILoggerFactory loggerFactory) - : base(configuration, hostingEnvironment, loggerFactory) - { - } - - /// - public override string ReceiverName => GitHubConstants.ReceiverName; - - /// - public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - if (next == null) - { - throw new ArgumentNullException(nameof(next)); - } - - var routeData = context.RouteData; - var request = context.HttpContext.Request; - if (routeData.TryGetWebHookReceiverName(out var receiverName) && - IsApplicable(receiverName) && - HttpMethods.IsPost(request.Method)) - { - // 1. Confirm a secure connection. - var errorResult = EnsureSecureConnection(ReceiverName, context.HttpContext.Request); - if (errorResult != null) - { - context.Result = errorResult; - return; - } - - // 2. Get the expected hash from the signature header. - var header = GetRequestHeader(request, GitHubConstants.SignatureHeaderName, out errorResult); - if (errorResult != null) - { - context.Result = errorResult; - return; - } - - var values = new TrimmingTokenizer(header, PairSeparators); - var enumerator = values.GetEnumerator(); - enumerator.MoveNext(); - var headerKey = enumerator.Current; - if (values.Count != 2 || - !StringSegment.Equals( - headerKey, - GitHubConstants.SignatureHeaderKey, - StringComparison.OrdinalIgnoreCase)) - { - Logger.LogError( - 1, - "Invalid '{HeaderName}' header value. Expecting a value of '{Key}={Value}'.", - GitHubConstants.SignatureHeaderName, - GitHubConstants.SignatureHeaderKey, - ""); - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.SignatureFilter_BadHeaderValue, - GitHubConstants.SignatureHeaderName, - GitHubConstants.SignatureHeaderKey, - ""); - errorResult = new BadRequestObjectResult(message); - - context.Result = errorResult; - return; - } - - enumerator.MoveNext(); - var headerValue = enumerator.Current.Value; - var expectedHash = GetDecodedHash(headerValue, GitHubConstants.SignatureHeaderName, out errorResult); - if (errorResult != null) - { - context.Result = errorResult; - return; - } - - // 3. Get the configured secret key. - var secretKey = GetSecretKey( - ReceiverName, - routeData, - GitHubConstants.SecretKeyMinLength, - GitHubConstants.SecretKeyMaxLength); - if (secretKey == null) - { - context.Result = new NotFoundResult(); - return; - } - - var secret = Encoding.UTF8.GetBytes(secretKey); - - // 4. Get the actual hash of the request body. - var actualHash = await GetRequestBodyHash_SHA1(request, secret); - - // 5. Verify that the actual hash matches the expected hash. - if (!SecretEqual(expectedHash, actualHash)) - { - // Log about the issue and short-circuit remainder of the pipeline. - errorResult = CreateBadSignatureResult(receiverName, GitHubConstants.SignatureHeaderName); - - context.Result = errorResult; - return; - } - } - - await next(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/GitHubConstants.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/GitHubConstants.cs deleted file mode 100644 index 8f225f2..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/GitHubConstants.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Well-known names and values used in GitHub receivers and handlers. - /// - public static class GitHubConstants - { - /// - /// Gets the name of the GitHub WebHook receiver. - /// - public static string ReceiverName => "github"; - - /// - /// Gets the name of the header containing the GitHub event name e.g. ping or push. - /// - public static string EventHeaderName => "X-Github-Event"; - - /// - /// Gets the name of the GitHub ping event. - /// - public static string PingEventName => "ping"; - - /// - /// Gets the minimum length of the secret key configured for this receiver. - /// - public static int SecretKeyMinLength => 16; - - /// - /// Gets the maximum length of the secret key configured for this receiver. - /// - public static int SecretKeyMaxLength => 128; - - /// - /// Gets the key of the hex-encoded signature in the value. - /// - public static string SignatureHeaderKey => "sha1"; - - /// - /// Gets the name of the HTTP header containing key / value pairs, including the (hex-encoded) signature of the - /// request. - /// - public static string SignatureHeaderName => "X-Hub-Signature"; - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/GitHubWebHookAttribute.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/GitHubWebHookAttribute.cs deleted file mode 100644 index d47511b..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/GitHubWebHookAttribute.cs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.AspNetCore.WebHooks.Properties; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// - /// An indicating the associated action is a GitHub WebHook endpoint. Specifies whether - /// the action should , optional , and optional - /// . Also adds a for the - /// action. - /// - /// - /// The signature of the action should be: - /// - /// Task{IActionResult} ActionName(string id, string @event, TData data) - /// - /// or include the subset of parameters required. TData must be compatible with expected requests. - /// - /// - /// An example GitHub WebHook URI is 'https://{host}/api/webhooks/incoming/github/{id}'. See - /// for additional details about GitHub WebHook requests. - /// - /// - /// - /// - /// If the application enables CORS in general (see the Microsoft.AspNetCore.Cors package), apply - /// DisableCorsAttribute to this action. If the application depends on the - /// Microsoft.AspNetCore.Mvc.ViewFeatures package, apply IgnoreAntiforgeryTokenAttribute to this - /// action. - /// - /// - /// should be used at most once per and - /// in a WebHook application. - /// - /// - public class GitHubWebHookAttribute : WebHookAttribute, IWebHookBodyTypeMetadata, IWebHookEventSelectorMetadata - { - private string _eventName; - - /// - /// Instantiates a new indicating the associated action is a GitHub - /// WebHook endpoint. - /// - public GitHubWebHookAttribute() - : base(GitHubConstants.ReceiverName) - { - } - - /// - /// Gets or sets an indication this action expects HTML form URL-encoded data. - /// - /// Defaults to , indicating this action expects JSON data. - public bool AcceptFormData { get; set; } - - /// - /// Gets or sets the name of the event the associated controller action accepts. - /// - /// Default value is , indicating this action accepts all events. - public string EventName - { - get - { - return _eventName; - } - set - { - if (string.IsNullOrEmpty(value)) - { - throw new ArgumentException(Resources.General_ArgumentCannotBeNullOrEmpty, nameof(value)); - } - - _eventName = value; - } - } - - /// - WebHookBodyType IWebHookBodyTypeMetadata.BodyType => AcceptFormData ? - WebHookBodyType.Form : - WebHookBodyType.Json; - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Internal/GitHubServiceCollectionSetup.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Internal/GitHubServiceCollectionSetup.cs deleted file mode 100644 index 3e9e51b..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Internal/GitHubServiceCollectionSetup.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.WebHooks.Filters; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Options; - -namespace Microsoft.AspNetCore.WebHooks.Internal -{ - /// - /// Methods to add services for the GitHub receiver. - /// - public static class GitHubServiceCollectionSetup - { - /// - /// Add services for the GitHub receiver. - /// - /// The to update. - public static void AddGitHubServices(IServiceCollection services) - { - if (services == null) - { - throw new ArgumentNullException(nameof(services)); - } - - services.TryAddEnumerable(ServiceDescriptor.Transient, MvcOptionsSetup>()); - services.TryAddEnumerable(ServiceDescriptor.Singleton()); - - services.TryAddSingleton(); - } - - private class MvcOptionsSetup : IConfigureOptions - { - /// - public void Configure(MvcOptions options) - { - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } - - options.Filters.AddService(WebHookSecurityFilter.Order); - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Metadata/GitHubMetadata.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Metadata/GitHubMetadata.cs deleted file mode 100644 index 56f2363..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Metadata/GitHubMetadata.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// An service containing metadata about the GitHub receiver. - /// - public class GitHubMetadata : WebHookMetadata, IWebHookEventMetadata, IWebHookPingRequestMetadata - { - /// - /// Instantiates a new instance. - /// - public GitHubMetadata() - : base(GitHubConstants.ReceiverName) - { - } - - // IWebHookEventMetadata... - - /// - public string ConstantValue => null; - - /// - public string HeaderName => GitHubConstants.EventHeaderName; - - /// - public string QueryParameterName => null; - - // IWebHookPingRequestMetadata... - - /// - public string PingEventName => GitHubConstants.PingEventName; - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Microsoft.AspNetCore.WebHooks.Receivers.GitHub.csproj b/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Microsoft.AspNetCore.WebHooks.Receivers.GitHub.csproj deleted file mode 100644 index 8b59eb4..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Microsoft.AspNetCore.WebHooks.Receivers.GitHub.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - $(Configurations);CodeAnalysis - ASP.NET Core GitHub WebHooks infrastructure. Contains the GitHubWebHookAttribute class and AddGitHubWebHooks method. - aspnetcore;webhook;receiver;github - - - - - Utilities\TrimmingTokenizer.cs - - - - - diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Properties/AssemblyInfo.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Properties/AssemblyInfo.cs deleted file mode 100644 index 0ac6215..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Microsoft.AspNetCore.WebHooks.Receivers.GitHub.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Properties/Resources.Designer.cs deleted file mode 100644 index 6d5d46d..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Properties/Resources.Designer.cs +++ /dev/null @@ -1,81 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Microsoft.AspNetCore.WebHooks.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.AspNetCore.WebHooks.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to Value cannot be null or empty.. - /// - internal static string General_ArgumentCannotBeNullOrEmpty { - get { - return ResourceManager.GetString("General_ArgumentCannotBeNullOrEmpty", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid '{0}' header value. Expecting a value of '{1}={2}'.. - /// - internal static string SignatureFilter_BadHeaderValue { - get { - return ResourceManager.GetString("SignatureFilter_BadHeaderValue", resourceCulture); - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Properties/Resources.resx b/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Properties/Resources.resx deleted file mode 100644 index 601992c..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.GitHub/Properties/Resources.resx +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Value cannot be null or empty. - - - Invalid '{0}' header value. Expecting a value of '{1}={2}'. - - \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/Extensions/KuduMvcBuilderExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/Extensions/KuduMvcBuilderExtensions.cs deleted file mode 100644 index 80d0300..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/Extensions/KuduMvcBuilderExtensions.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using Microsoft.AspNetCore.WebHooks.Internal; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up Kudu WebHooks in an . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class KuduMvcBuilderExtensions - { - /// - /// - /// Add Kudu WebHook configuration and services to the specified . See - /// for additional details about Kudu WebHook - /// requests. - /// - /// - /// The 'WebHooks:Kudu:SecretKey:default' configuration value contains the secret key for Kudu WebHook - /// URIs of the form 'https://{host}/api/webhooks/incoming/kudu?code={secret key}'. - /// 'WebHooks:Kudu:SecretKey:{id}' configuration values contain secret keys for Kudu WebHook URIs of the - /// form 'https://{host}/api/webhooks/incoming/kudu/{id}?code={secret key}'. - /// - /// - /// The to configure. - /// The . - public static IMvcBuilder AddKuduWebHooks(this IMvcBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - KuduServiceCollectionSetup.AddKuduServices(builder.Services); - - return builder.AddWebHooks(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/Extensions/KuduMvcCoreBuilderExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/Extensions/KuduMvcCoreBuilderExtensions.cs deleted file mode 100644 index a57dcef..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/Extensions/KuduMvcCoreBuilderExtensions.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using Microsoft.AspNetCore.WebHooks.Internal; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up Kudu WebHooks in an . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class KuduMvcCoreBuilderExtensions - { - /// - /// - /// Add Kudu WebHook configuration and services to the specified . See - /// for additional details about Kudu WebHook - /// requests. - /// - /// - /// The 'WebHooks:Kudu:SecretKey:default' configuration value contains the secret key for Kudu WebHook - /// URIs of the form 'https://{host}/api/webhooks/incoming/kudu?code={secret key}'. - /// 'WebHooks:Kudu:SecretKey:{id}' configuration values contain secret keys for Kudu WebHook URIs of the - /// form 'https://{host}/api/webhooks/incoming/kudu/{id}?code={secret key}'. - /// - /// - /// The to configure. - /// The . - public static IMvcCoreBuilder AddKuduWebHooks(this IMvcCoreBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - KuduServiceCollectionSetup.AddKuduServices(builder.Services); - - return builder - .AddJsonFormatters() - .AddWebHooks(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/Internal/KuduServiceCollectionSetup.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/Internal/KuduServiceCollectionSetup.cs deleted file mode 100644 index dd34306..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/Internal/KuduServiceCollectionSetup.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; - -namespace Microsoft.AspNetCore.WebHooks.Internal -{ - /// - /// Methods to add services for the Kudu receiver. - /// - public static class KuduServiceCollectionSetup - { - /// - /// Add services for the Kudu receiver. - /// - /// The to update. - public static void AddKuduServices(IServiceCollection services) - { - if (services == null) - { - throw new ArgumentNullException(nameof(services)); - } - - services.TryAddEnumerable(ServiceDescriptor.Singleton()); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/KuduConstants.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/KuduConstants.cs deleted file mode 100644 index 6f3d9a5..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/KuduConstants.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Well-known names used in Kudu receivers and handlers. - /// - public static class KuduConstants - { - /// - /// Gets the JSON path of the property in a Kudu WebHook request body containing the Kudu event name. - /// - public static string EventBodyPropertyPath => "$.status"; - - /// - /// Gets the name of the Kudu WebHook receiver. - /// - public static string ReceiverName => "kudu"; - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/KuduNotification.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/KuduNotification.cs deleted file mode 100644 index 1557efe..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/KuduNotification.cs +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Newtonsoft.Json; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Contains information sent in a WebHook notification from Kudu (Azure Web App Deployment Service). - /// - public class KuduNotification - { - /// - /// Gets or sets the ID of the WebHook. - /// - [JsonProperty("id")] - public string Id { get; set; } - - /// - /// Gets or sets the status of the WebHook, e.g. success - /// - [JsonProperty("status")] - public string Status { get; set; } - - /// - /// Gets or sets the status text of the WebHook. - /// - [JsonProperty("statusText")] - public string StatusText { get; set; } - - /// - /// Gets or sets the email of the author generating the WebHook. - /// - [JsonProperty("authorEmail")] - public string AuthorEmail { get; set; } - - /// - /// Gets or sets the name of the author generating the WebHook. - /// - [JsonProperty("author")] - public string Author { get; set; } - - /// - /// Gets or sets a message contained within the WebHook. - /// - [JsonProperty("message")] - public string Message { get; set; } - - /// - /// Gets or sets a progress indication. - /// - [JsonProperty("progress")] - public string Progress { get; set; } - - /// - /// Gets or sets the user name of the deployer causing the WebHook to be generated. - /// - [JsonProperty("deployer")] - public string Deployer { get; set; } - - /// - /// Gets or sets the time the operation was received by Kudu. - /// - [JsonProperty("receivedTime")] - public DateTime ReceivedTime { get; set; } - - /// - /// Gets or sets the time the operation was started by Kudu. - /// - [JsonProperty("startTime")] - public DateTime StartTime { get; set; } - - /// - /// Gets or sets the time the operation was completed by Kudu. - /// - [JsonProperty("endTime")] - public DateTime EndTime { get; set; } - - /// - /// Gets or sets the time the last successful operation was completed. - /// - [JsonProperty("lastSuccessEndTime")] - public DateTime LastSuccessEndTime { get; set; } - - /// - /// Gets or sets a value indicating whether the operation is complete. - /// - [JsonProperty("complete")] - public bool Complete { get; set; } - - /// - /// Gets or sets the name of the site the operation is targeting. - /// - [JsonProperty("siteName")] - public string SiteName { get; set; } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/KuduWebHookAttribute.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/KuduWebHookAttribute.cs deleted file mode 100644 index 69fadb9..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/KuduWebHookAttribute.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// - /// An indicating the associated action is a Kudu WebHook endpoint. Specifies the - /// optional . Also adds a for - /// the action. - /// - /// - /// The signature of the action should be: - /// - /// Task{IActionResult} ActionName(string id, string @event, TData data) - /// - /// or include the subset of parameters required. TData must be compatible with expected requests e.g. - /// or . - /// - /// - /// An example Kudu WebHook URI is - /// 'https://{host}/api/webhooks/incoming/kudu/{id}?code=83699ec7c1d794c0c780e49a5c72972590571fd8'. - /// See for additional details about Kudu WebHook - /// requests. - /// - /// - /// - /// - /// If the application enables CORS in general (see the Microsoft.AspNetCore.Cors package), apply - /// DisableCorsAttribute to this action. If the application depends on the - /// Microsoft.AspNetCore.Mvc.ViewFeatures package, apply IgnoreAntiforgeryTokenAttribute to this - /// action. - /// - /// - /// should be used at most once per in a - /// WebHook application. - /// - /// - public class KuduWebHookAttribute : WebHookAttribute - { - /// - /// Instantiates a new indicating the associated action is a Kudu WebHook - /// endpoint. - /// - public KuduWebHookAttribute() - : base(KuduConstants.ReceiverName) - { - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/Metadata/KuduMetadata.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/Metadata/KuduMetadata.cs deleted file mode 100644 index dd5a95a..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/Metadata/KuduMetadata.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// An service containing metadata about the Kudu receiver. - /// - public class KuduMetadata : - WebHookMetadata, - IWebHookBodyTypeMetadataService, - IWebHookEventFromBodyMetadata, - IWebHookVerifyCodeMetadata - { - /// - /// Instantiates a new instance. - /// - public KuduMetadata() - : base(KuduConstants.ReceiverName) - { - } - - // IWebHookBodyTypeMetadataService... - - /// - public WebHookBodyType BodyType => WebHookBodyType.Json; - - // IWebHookEventFromBodyMetadata... - - /// - public bool AllowMissing => false; - - /// - public string BodyPropertyPath => KuduConstants.EventBodyPropertyPath; - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/Microsoft.AspNetCore.WebHooks.Receivers.Kudu.csproj b/src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/Microsoft.AspNetCore.WebHooks.Receivers.Kudu.csproj deleted file mode 100644 index d026f8d..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Kudu/Microsoft.AspNetCore.WebHooks.Receivers.Kudu.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - $(Configurations);CodeAnalysis - ASP.NET Core Kudu WebHooks infrastructure. Contains the KuduWebHookAttribute class and AddKuduWebHooks method. - aspnetcore;webhook;receiver;kudu - - - - - - - diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/Extensions/MailChimpMvcBuilderExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/Extensions/MailChimpMvcBuilderExtensions.cs deleted file mode 100644 index 43e827a..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/Extensions/MailChimpMvcBuilderExtensions.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using Microsoft.AspNetCore.WebHooks.Internal; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up MailChimp WebHooks in an . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class MailChimpMvcBuilderExtensions - { - /// - /// - /// Add MailChimp WebHook configuration and services to the specified . See - /// for additional - /// details about MailChimp WebHook requests. - /// - /// - /// The 'WebHooks:MailChimp:SecretKey:default' configuration value contains the secret key for MailChimp - /// WebHook URIs of the form 'https://{host}/api/webhooks/incoming/mailchimp?code={secret key}'. - /// 'WebHooks:MailChimp:SecretKey:{id}' configuration values contain secret keys for MailChimp WebHook - /// URIs of the form 'https://{host}/api/webhooks/incoming/mailchimp/{id}?code={secret key}'. - /// - /// - /// The to configure. - /// The . - public static IMvcBuilder AddMailChimpWebHooks(this IMvcBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - MailChimpServiceCollectionSetup.AddMailChimpServices(builder.Services); - - return builder.AddWebHooks(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/Extensions/MailChimpMvcCoreBuilderExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/Extensions/MailChimpMvcCoreBuilderExtensions.cs deleted file mode 100644 index f39c3e9..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/Extensions/MailChimpMvcCoreBuilderExtensions.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using Microsoft.AspNetCore.WebHooks.Internal; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up MailChimp WebHooks in an . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class MailChimpMvcCoreBuilderExtensions - { - /// - /// - /// Add MailChimp WebHook configuration and services to the specified . See - /// for additional - /// details about MailChimp WebHook requests. - /// - /// - /// The 'WebHooks:MailChimp:SecretKey:default' configuration value contains the secret key for MailChimp - /// WebHook URIs of the form 'https://{host}/api/webhooks/incoming/mailchimp'. - /// 'WebHooks:MailChimp:SecretKey:{id}' configuration values contain secret keys for MailChimp WebHook - /// URIs of the form 'https://{host}/api/webhooks/incoming/mailchimp/{id}'. - /// - /// - /// The to configure. - /// The . - public static IMvcCoreBuilder AddMailChimpWebHooks(this IMvcCoreBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - MailChimpServiceCollectionSetup.AddMailChimpServices(builder.Services); - - return builder.AddWebHooks(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/Internal/MailChimpServiceCollectionSetup.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/Internal/MailChimpServiceCollectionSetup.cs deleted file mode 100644 index 5815852..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/Internal/MailChimpServiceCollectionSetup.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; - -namespace Microsoft.AspNetCore.WebHooks.Internal -{ - /// - /// Methods to add services for the MailChimp receiver. - /// - public static class MailChimpServiceCollectionSetup - { - /// - /// Add services for the MailChimp receiver. - /// - /// The to update. - public static void AddMailChimpServices(IServiceCollection services) - { - if (services == null) - { - throw new ArgumentNullException(nameof(services)); - } - - services.TryAddEnumerable(ServiceDescriptor.Singleton()); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/MailChimpConstants.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/MailChimpConstants.cs deleted file mode 100644 index e072b31..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/MailChimpConstants.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Well-known names used in MailChimp receivers and handlers. - /// - public static class MailChimpConstants - { - /// - /// Gets the name of the property in a MailChimp WebHook request entity body (formatted as HTML form - /// URL-encoded data) containing the MailChimp event name. - /// - public static string EventBodyPropertyName => "type"; - - /// - /// Gets the name of the MailChimp WebHook receiver. - /// - public static string ReceiverName => "mailchimp"; - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/MailChimpWebHookAttribute.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/MailChimpWebHookAttribute.cs deleted file mode 100644 index 8060e4d..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/MailChimpWebHookAttribute.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// - /// An indicating the associated action is a MailChimp WebHook endpoint. Specifies - /// the optional . Also adds a - /// for the action. - /// - /// - /// The signature of the action should be: - /// - /// Task{IActionResult} ActionName(string id, string @event, TData data) - /// - /// or include the subset of parameters required. TData must be compatible with expected requests e.g. - /// . - /// - /// - /// An example MailChimp WebHook URI is - /// 'https://{host}/api/webhooks/incoming/mailchimp/{id}?code=83699ec7c1d794c0c780e49a5c72972590571fd8'. - /// See for additional - /// details about MailChimp WebHook requests. - /// - /// - /// - /// - /// If the application enables CORS in general (see the Microsoft.AspNetCore.Cors package), apply - /// DisableCorsAttribute to this action. If the application depends on the - /// Microsoft.AspNetCore.Mvc.ViewFeatures package, apply IgnoreAntiforgeryTokenAttribute to this - /// action. - /// - /// - /// should be used at most once per in a - /// WebHook application. - /// - /// - public class MailChimpWebHookAttribute : WebHookAttribute - { - /// - /// Instantiates a new indicating the associated action is a MailChimp - /// WebHook endpoint. - /// - public MailChimpWebHookAttribute() - : base(MailChimpConstants.ReceiverName) - { - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/Metadata/MailChimpMetadata.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/Metadata/MailChimpMetadata.cs deleted file mode 100644 index 2fcfdc0..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/Metadata/MailChimpMetadata.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// An service containing metadata about the MailChimp receiver. - /// - public class MailChimpMetadata : - WebHookMetadata, - IWebHookBodyTypeMetadataService, - IWebHookEventFromBodyMetadata, - IWebHookGetRequestMetadata, - IWebHookVerifyCodeMetadata - { - /// - /// Instantiates a new instance. - /// - public MailChimpMetadata() - : base(MailChimpConstants.ReceiverName) - { - } - - // IWebHookBodyTypeMetadataService... - - /// - public WebHookBodyType BodyType => WebHookBodyType.Form; - - // IWebHookEventFromBodyMetadata... - - /// - public bool AllowMissing => false; - - /// - public string BodyPropertyPath => MailChimpConstants.EventBodyPropertyName; - - // IWebHookGetRequestMetadata... - - /// - public string ChallengeQueryParameterName => null; - - /// - public int SecretKeyMinLength => WebHookConstants.CodeParameterMinLength; - - /// - public int SecretKeyMaxLength => WebHookConstants.CodeParameterMaxLength; - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp.csproj b/src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp.csproj deleted file mode 100644 index 6059cc9..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp/Microsoft.AspNetCore.WebHooks.Receivers.MailChimp.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - $(Configurations);CodeAnalysis - ASP.NET Core MailChimp WebHooks infrastructure. Contains the MailChimpWebHookAttribute class and AddMailChimpWebHooks method. - aspnetcore;webhook;receiver;mailchimp - - - - - - diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Extensions/PusherMvcBuilderExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Extensions/PusherMvcBuilderExtensions.cs deleted file mode 100644 index 9f1d36d..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Extensions/PusherMvcBuilderExtensions.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using Microsoft.AspNetCore.WebHooks.Internal; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up Pusher WebHooks in an . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class PusherMvcBuilderExtensions - { - /// - /// - /// Add Pusher WebHook configuration and services to the specified . See - /// for additional details about Pusher WebHook requests. - /// - /// - /// 'WebHooks:Pusher:SecretKey:default:{application key}' configuration values contain secret keys for - /// Pusher WebHook URIs of the form 'https://{host}/api/webhooks/incoming/pusher'. - /// 'WebHooks:Pusher:SecretKey:{id}:{application key}' configuration values contain secret keys for - /// Pusher WebHook URIs of the form 'https://{host}/api/webhooks/incoming/pusher/{id}'. Users optionally - /// provide {id} values while Pusher defines the {application key} / secret key pairs. - /// - /// - /// The to configure. - /// The . - public static IMvcBuilder AddPusherWebHooks(this IMvcBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - PusherServiceCollectionSetup.AddPusherServices(builder.Services); - - return builder.AddWebHooks(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Extensions/PusherMvcCoreBuilderExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Extensions/PusherMvcCoreBuilderExtensions.cs deleted file mode 100644 index 69ab336..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Extensions/PusherMvcCoreBuilderExtensions.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using Microsoft.AspNetCore.WebHooks.Internal; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up Pusher WebHooks in an . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class PusherMvcCoreBuilderExtensions - { - /// - /// - /// Add Pusher WebHook configuration and services to the specified . See - /// for additional details about Pusher WebHook requests. - /// - /// - /// 'WebHooks:Pusher:SecretKey:default:{application key}' configuration values contain secret keys for - /// Pusher WebHook URIs of the form 'https://{host}/api/webhooks/incoming/pusher'. - /// 'WebHooks:Pusher:SecretKey:{id}:{application key}' configuration values contain secret keys for - /// Pusher WebHook URIs of the form 'https://{host}/api/webhooks/incoming/pusher/{id}'. Users optionally - /// provide {id} values while Pusher defines the {application key} / secret key pairs. - /// - /// - /// The to configure. - /// The . - public static IMvcCoreBuilder AddPusherWebHooks(this IMvcCoreBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - PusherServiceCollectionSetup.AddPusherServices(builder.Services); - - return builder - .AddJsonFormatters() - .AddWebHooks(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Filters/PusherVerifySignatureFilter.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Filters/PusherVerifySignatureFilter.cs deleted file mode 100644 index 4689ec4..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Filters/PusherVerifySignatureFilter.cs +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Globalization; -using System.Text; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.WebHooks.Properties; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; - -namespace Microsoft.AspNetCore.WebHooks.Filters -{ - /// - /// An that verifies the Pusher signature header. Confirms the header exists, - /// reads Body bytes, and compares the hashes. - /// - public class PusherVerifySignatureFilter : WebHookVerifySignatureFilter, IAsyncResourceFilter - { - /// - /// Instantiates a new instance. - /// - /// - /// The used to initialize . - /// - /// - /// The used to initialize - /// . - /// - /// - /// The used to initialize . - /// - public PusherVerifySignatureFilter( - IConfiguration configuration, - IHostingEnvironment hostingEnvironment, - ILoggerFactory loggerFactory) - : base(configuration, hostingEnvironment, loggerFactory) - { - } - - /// - public override string ReceiverName => PusherConstants.ReceiverName; - - /// - public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - if (next == null) - { - throw new ArgumentNullException(nameof(next)); - } - - var routeData = context.RouteData; - var request = context.HttpContext.Request; - if (routeData.TryGetWebHookReceiverName(out var receiverName) && - IsApplicable(receiverName) && - HttpMethods.IsPost(request.Method)) - { - // 1. Confirm a secure connection. - var errorResult = EnsureSecureConnection(ReceiverName, context.HttpContext.Request); - if (errorResult != null) - { - context.Result = errorResult; - return; - } - - // 2. Get the expected hash from the signature headers. - var header = GetRequestHeader(request, PusherConstants.SignatureHeaderName, out errorResult); - if (errorResult != null) - { - context.Result = errorResult; - return; - } - - var expectedHash = GetDecodedHash(header, PusherConstants.SignatureHeaderName, out errorResult); - if (errorResult != null) - { - context.Result = errorResult; - return; - } - - // 3. Get the configured secret key. - var secretKeys = GetSecretKeys(ReceiverName, routeData); - if (!secretKeys.Exists()) - { - context.Result = new NotFoundResult(); - return; - } - - var applicationKey = GetRequestHeader(request, PusherConstants.SignatureKeyHeaderName, out errorResult); - if (errorResult != null) - { - context.Result = errorResult; - return; - } - - var secretKey = secretKeys[applicationKey]; - if (secretKey == null || - secretKey.Length < PusherConstants.SecretKeyMinLength || - secretKey.Length > PusherConstants.SecretKeyMaxLength) - { - Logger.LogError( - 0, - "The '{HeaderName}' header value of '{HeaderValue}' is not recognized as a valid " + - "application key. Please ensure the correct application key / secret key pairs have " + - "been configured.", - PusherConstants.SignatureKeyHeaderName, - applicationKey); - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.SignatureFilter_SecretNotFound, - PusherConstants.SignatureKeyHeaderName, - applicationKey); - - context.Result = new BadRequestObjectResult(message); - return; - } - - var secret = Encoding.UTF8.GetBytes(secretKey); - - // 4. Get the actual hash of the request body. - var actualHash = await GetRequestBodyHash_SHA256(request, secret); - - // 5. Verify that the actual hash matches the expected hash. - if (!SecretEqual(expectedHash, actualHash)) - { - // Log about the issue and short-circuit remainder of the pipeline. - errorResult = CreateBadSignatureResult(receiverName, PusherConstants.SignatureHeaderName); - - context.Result = errorResult; - return; - } - } - - await next(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Internal/PusherServiceCollectionSetup.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Internal/PusherServiceCollectionSetup.cs deleted file mode 100644 index 4b9ebcf..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Internal/PusherServiceCollectionSetup.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.WebHooks.Filters; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Options; - -namespace Microsoft.AspNetCore.WebHooks.Internal -{ - /// - /// Methods to add services for the Pusher receiver. - /// - public static class PusherServiceCollectionSetup - { - /// - /// Add services for the Pusher receiver. - /// - /// The to update. - public static void AddPusherServices(IServiceCollection services) - { - if (services == null) - { - throw new ArgumentNullException(nameof(services)); - } - - services.TryAddEnumerable(ServiceDescriptor.Transient, MvcOptionsSetup>()); - services.TryAddEnumerable(ServiceDescriptor.Singleton()); - - services.TryAddSingleton(); - } - - private class MvcOptionsSetup : IConfigureOptions - { - /// - public void Configure(MvcOptions options) - { - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } - - options.Filters.AddService(WebHookSecurityFilter.Order); - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Metadata/PusherMetadata.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Metadata/PusherMetadata.cs deleted file mode 100644 index 1914bdd..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Metadata/PusherMetadata.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// An service containing metadata about the Pusher receiver. - /// - public class PusherMetadata : WebHookMetadata, IWebHookBodyTypeMetadataService, IWebHookEventFromBodyMetadata - { - /// - /// Instantiates a new instance. - /// - public PusherMetadata() - : base(PusherConstants.ReceiverName) - { - } - - // IWebHookBodyTypeMetadataService... - - /// - public WebHookBodyType BodyType => WebHookBodyType.Json; - - // IWebHookEvenFromBodytMetadata... - - /// - public bool AllowMissing => true; - - /// - public string BodyPropertyPath => PusherConstants.EventBodyPropertyPath; - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Microsoft.AspNetCore.WebHooks.Receivers.Pusher.csproj b/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Microsoft.AspNetCore.WebHooks.Receivers.Pusher.csproj deleted file mode 100644 index 9b729ad..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Microsoft.AspNetCore.WebHooks.Receivers.Pusher.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - $(Configurations);CodeAnalysis - ASP.NET Core Pusher WebHooks infrastructure. Contains the PusherWebHookAttribute class and AddPusherWebHooks method. - aspnetcore;webhook;receiver;pusher - - - - - - - diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Properties/Resources.Designer.cs deleted file mode 100644 index d05ec30..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Properties/Resources.Designer.cs +++ /dev/null @@ -1,72 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Microsoft.AspNetCore.WebHooks.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.AspNetCore.WebHooks.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to The '{0}' header value of '{1}' is not recognized as a valid application key. Please ensure the correct application key / secret key pairs have been configured.. - /// - internal static string SignatureFilter_SecretNotFound { - get { - return ResourceManager.GetString("SignatureFilter_SecretNotFound", resourceCulture); - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Properties/Resources.resx b/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Properties/Resources.resx deleted file mode 100644 index f59722c..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/Properties/Resources.resx +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - The '{0}' header value of '{1}' is not recognized as a valid application key. Please ensure the correct application key / secret key pairs have been configured. - - \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/PusherConstants.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/PusherConstants.cs deleted file mode 100644 index 13620bf..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/PusherConstants.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Well-known names and values used in Pusher receivers and handlers. - /// - public static class PusherConstants - { - /// - /// Gets the JSON path of the properties in a Pusher WebHook request body containing the Pusher event names. - /// - /// - /// Combines and . - /// - public static string EventBodyPropertyPath => "$['events'][*]['name']"; - - /// - /// Gets the name of the JSON property in a Pusher WebHook request body containing its Unix creation timestamp. - /// - public static string EventRequestCreatedAtPropertyName => "time_ms"; - - /// - /// Gets the name of the JSON property in a Pusher WebHook request body containing a JSON array holding the - /// individual event details. Each event object contains an property and - /// usually contains a property. - /// - public static string EventRequestPropertyContainerName => "events"; - - /// - /// Gets the name of the JSON property in most Pusher event objects containing the event's channel name. - /// - public static string ChannelNamePropertyName => "channel"; - - /// - /// Gets the name of the JSON property in a Pusher event object containing the event's name. - /// - public static string EventNamePropertyName => "name"; - - /// - /// Gets the name of the Pusher WebHook receiver. - /// - public static string ReceiverName => "pusher"; - - /// - /// Gets the minimum length of the secret key configured for this receiver. - /// - public static int SecretKeyMinLength => 8; - - /// - /// Gets the maximum length of the secret key configured for this receiver. - /// - public static int SecretKeyMaxLength => 128; - - /// - /// Gets the name of the HTTP header containing the key into the configured lookup table. Named entry in the - /// table contains the secret key the sender used when generating the value. - /// - public static string SignatureKeyHeaderName => "X-Pusher-Key"; - - /// - /// Gets the name of the HTTP header containing the (hex-encoded) signature of the request. - /// - public static string SignatureHeaderName => "X-Pusher-Signature"; - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/PusherNotifications.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/PusherNotifications.cs deleted file mode 100644 index bdbaeba..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/PusherNotifications.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Describes one or more event notifications received as a Pusher WebHook. - /// For details about Pusher WebHooks, see https://pusher.com/docs/webhooks. - /// - public class PusherNotifications - { - private readonly List> _events = new List>(); - - /// - /// Gets or sets a Unix time stamp in milliseconds which can be used to determine the order in which - /// Pusher events were generated. For conversion of Unix timestamps to , - /// please see https://msdn.microsoft.com/en-us/library/system.datetimeoffset.fromunixtimemilliseconds. - /// - [JsonProperty("time_ms")] - public long CreatedAt { get; set; } - - /// - /// Gets the set of events contained in this notification from a Pusher WebHook. Each notification - /// is represented as a where TKey is a property - /// name and TValue is the value of that property. For each notification, the Action - /// can be found using the key 'name'. - /// - [JsonProperty("events")] - public ICollection> Events - { - get - { - return _events; - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/PusherWebHookAttribute.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/PusherWebHookAttribute.cs deleted file mode 100644 index 8085ce9..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Pusher/PusherWebHookAttribute.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// - /// An indicating the associated action is a Pusher WebHook endpoint. Specifies the - /// optional . Also adds a for - /// the action. - /// - /// - /// The signature of the action should be: - /// - /// Task{IActionResult} ActionName(string id, string[] events, TData data) - /// - /// or include the subset of parameters required. TData must be compatible with expected requests e.g. - /// or . - /// - /// - /// An example Pusher WebHook URI is 'https://{host}/api/webhooks/incoming/pusher/{id}'. See - /// for additional details about Pusher WebHook requests. - /// - /// - /// - /// - /// If the application enables CORS in general (see the Microsoft.AspNetCore.Cors package), apply - /// DisableCorsAttribute to this action. If the application depends on the - /// Microsoft.AspNetCore.Mvc.ViewFeatures package, apply IgnoreAntiforgeryTokenAttribute to this - /// action. - /// - /// - /// should be used at most once per in a - /// WebHook application. - /// - /// - public class PusherWebHookAttribute : WebHookAttribute - { - /// - /// Instantiates a new indicating the associated action is a Pusher - /// WebHook endpoint. - /// - public PusherWebHookAttribute() - : base(PusherConstants.ReceiverName) - { - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Extensions/SalesforceMvcBuilderExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Extensions/SalesforceMvcBuilderExtensions.cs deleted file mode 100644 index 4ad3ca9..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Extensions/SalesforceMvcBuilderExtensions.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using Microsoft.AspNetCore.WebHooks.Internal; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up Salesforce WebHooks in an . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class SalesforceMvcBuilderExtensions - { - /// - /// - /// Add Salesforce WebHook configuration and services to the specified . See - /// for additional details about Salesforce - /// WebHook requests. - /// - /// - /// The 'WebHooks:SalesforceSoap:SecretKey:default' configuration value contains the secret key for - /// Salesforce WebHook URIs of the form 'https://{host}/api/webhooks/incoming/sfsoap'. - /// 'WebHooks:SalesforceSoap:SecretKey:{id}' configuration values contain secret keys for Salesforce - /// WebHook URIs of the form 'https://{host}/api/webhooks/incoming/sfsoap/{id}'. Secret keys are - /// Salesforce Organization IDs and can be found at under - /// Setup | Company Profile | Company Information. - /// - /// - /// The to configure. - /// The . - public static IMvcBuilder AddSalesforceWebHooks(this IMvcBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - SalesforceServiceCollectionSetup.AddSalesforceServices(builder.Services); - - return builder - .AddXmlSerializerFormatters() - .AddWebHooks(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Extensions/SalesforceMvcCoreBuilderExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Extensions/SalesforceMvcCoreBuilderExtensions.cs deleted file mode 100644 index a823ca3..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Extensions/SalesforceMvcCoreBuilderExtensions.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using Microsoft.AspNetCore.WebHooks.Internal; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up Salesforce WebHooks in an . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class SalesforceMvcCoreBuilderExtensions - { - /// - /// - /// Add Salesforce WebHook configuration and services to the specified . See - /// for additional details about Salesforce - /// WebHook requests. - /// - /// - /// The 'WebHooks:SalesforceSoap:SecretKey:default' configuration value contains the secret key for - /// Salesforce WebHook URIs of the form 'https://{host}/api/webhooks/incoming/sfsoap'. - /// 'WebHooks:SalesforceSoap:SecretKey:{id}' configuration values contain secret keys for Salesforce - /// WebHook URIs of the form 'https://{host}/api/webhooks/incoming/sfsoap/{id}'. Secret keys are - /// Salesforce Organization IDs and can be found at under - /// Setup | Company Profile | Company Information. - /// - /// - /// The to configure. - /// The . - public static IMvcCoreBuilder AddSalesforceWebHooks(this IMvcCoreBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - SalesforceServiceCollectionSetup.AddSalesforceServices(builder.Services); - - return builder - .AddXmlSerializerFormatters() - .AddWebHooks(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Filters/SalesforceVerifyOrganizationIdFilter.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Filters/SalesforceVerifyOrganizationIdFilter.cs deleted file mode 100644 index 1d5f908..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Filters/SalesforceVerifyOrganizationIdFilter.cs +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Globalization; -using System.Threading.Tasks; -using System.Xml.Linq; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.WebHooks.Properties; -using Microsoft.AspNetCore.WebHooks.Utilities; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Primitives; - -namespace Microsoft.AspNetCore.WebHooks.Filters -{ - /// - /// An that verifies the Salesforce SOAP request body. Confirms the body - /// deserializes as that can be converted to . Then - /// confirms the organization id and event name is present and that the organization id matches the configured - /// secret key. - /// - public class SalesforceVerifyOrganizationIdFilter : WebHookSecurityFilter, IAsyncResourceFilter, IWebHookReceiver - { - private readonly ISalesforceResultCreator _resultCreator; - private readonly IWebHookRequestReader _requestReader; - - /// - /// Instantiates a new instance. - /// - /// - /// The used to initialize . - /// - /// - /// The used to initialize - /// . - /// - /// - /// The used to initialize . - /// - /// The . - /// The . - public SalesforceVerifyOrganizationIdFilter( - IConfiguration configuration, - IHostingEnvironment hostingEnvironment, - ILoggerFactory loggerFactory, - ISalesforceResultCreator resultCreator, - IWebHookRequestReader requestReader) - : base(configuration, hostingEnvironment, loggerFactory) - { - _resultCreator = resultCreator; - _requestReader = requestReader; - } - - /// - public string ReceiverName => SalesforceConstants.ReceiverName; - - /// - public bool IsApplicable(string receiverName) - { - if (receiverName == null) - { - throw new ArgumentNullException(nameof(receiverName)); - } - - return string.Equals(ReceiverName, receiverName, StringComparison.OrdinalIgnoreCase); - } - - /// - public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - if (next == null) - { - throw new ArgumentNullException(nameof(next)); - } - - // 1. Confirm this filter applies. - var routeData = context.RouteData; - if (!routeData.TryGetWebHookReceiverName(out var receiverName) || !IsApplicable(receiverName)) - { - await next(); - return; - } - - // 2. Confirm we were reached using HTTPS. - var request = context.HttpContext.Request; - var errorResult = EnsureSecureConnection(receiverName, request); - if (errorResult != null) - { - context.Result = errorResult; - return; - } - - // 3. Get XElement from the request body. - var data = await _requestReader.ReadBodyAsync(context); - if (data == null) - { - var modelState = context.ModelState; - if (modelState.IsValid) - { - // ReadAsXmlAsync returns null when model state is valid only when other filters will log and - // return errors about the same conditions. Let those filters run. - await next(); - } - else - { - context.Result = new BadRequestObjectResult(modelState); - } - - return; - } - - // 4. Ensure the organization ID exists and matches the expected value. - var organizationIds = ObjectPathUtilities.GetStringValues(data, SalesforceConstants.OrganizationIdPath); - if (StringValues.IsNullOrEmpty(organizationIds)) - { - Logger.LogError( - 0, - "The HTTP request body did not contain a required '{XPath}' element.", - SalesforceConstants.OrganizationIdPath); - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.VerifyOrganization_MissingValue, - SalesforceConstants.OrganizationIdPath); - context.Result = await _resultCreator.GetFailedResultAsync(message); - - return; - } - - var secret = GetSecretKey( - ReceiverName, - routeData, - SalesforceConstants.SecretKeyMinLength, - SalesforceConstants.SecretKeyMaxLength); - - var organizationId = GetShortOrganizationId(organizationIds[0]); - var secretKey = GetShortOrganizationId(secret); - if (!SecretEqual(organizationId, secretKey)) - { - Logger.LogError( - 1, - "The '{XPath}' value provided in the HTTP request body did not match the expected value.", - SalesforceConstants.OrganizationIdPath); - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.VerifyOrganization_BadValue, - SalesforceConstants.OrganizationIdPath); - context.Result = await _resultCreator.GetFailedResultAsync(message); - - return; - } - - // 5. Get the event name. - var eventNames = ObjectPathUtilities.GetStringValues(data, SalesforceConstants.EventNamePath); - if (StringValues.IsNullOrEmpty(eventNames)) - { - Logger.LogError( - 2, - "The HTTP request body did not contain a required '{XPath}' element.", - SalesforceConstants.EventNamePath); - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.VerifyOrganization_MissingValue, - SalesforceConstants.EventNamePath); - context.Result = await _resultCreator.GetFailedResultAsync(message); - - return; - } - - // 6. Success. Provide event name for model binding. - routeData.SetWebHookEventNames(eventNames); - - await next(); - } - - /// - /// Gets the shortened version of . - /// - /// The full organization name. - /// The shortened version of . - protected static string GetShortOrganizationId(string fullOrganizationId) - { - if (fullOrganizationId?.Length == 18) - { - return fullOrganizationId.Substring(0, 15); - } - - return fullOrganizationId; - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/ISalesforceResultCreator.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/ISalesforceResultCreator.cs deleted file mode 100644 index c6a4263..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/ISalesforceResultCreator.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Provides an abstraction for creating the SOAP responses Salesforce expects. - /// - public interface ISalesforceResultCreator - { - /// - /// Gets an that when executed will produce a response with status code 400 "Bad - /// Request" and an XML body containing . - /// - /// The error message string to include in the XML-formatted response. - /// - /// A that on completion provides an that when - /// executed will produce the desired response. - /// - Task GetFailedResultAsync(string message); - - /// - /// Gets an that when executed will produce a response with status code 200 "OK" - /// and an XML body containing a Salesforce acknowledgment message. - /// - /// - /// A that on completion provides an that when - /// executed will produce the desired response. - /// - Task GetSuccessResultAsync(); - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Internal/SalesforceResultCreator.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Internal/SalesforceResultCreator.cs deleted file mode 100644 index b01b4f7..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Internal/SalesforceResultCreator.cs +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Globalization; -using System.IO; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.WebHooks.Properties; -using Microsoft.Extensions.Logging; - -namespace Microsoft.AspNetCore.WebHooks.Internal -{ - /// - /// The default implementation. - /// - public class SalesforceResultCreator : ISalesforceResultCreator - { - private readonly ILogger _logger; - - /// - /// Instantiates a new instance. - /// - /// The . - public SalesforceResultCreator(ILoggerFactory loggerFactory) - { - _logger = loggerFactory.CreateLogger(); - } - - /// - public async Task GetFailedResultAsync(string message) - { - var resource = await GetResourceAsync("Microsoft.AspNetCore.WebHooks.Messages.FaultResponse.xml"); - var formattedResource = string.Format(CultureInfo.CurrentCulture, resource, message); - - return GetXmlResult(formattedResource, StatusCodes.Status400BadRequest); - } - - /// - public async Task GetSuccessResultAsync() - { - var resource = await GetResourceAsync("Microsoft.AspNetCore.WebHooks.Messages.NotificationResponse.xml"); - - return GetXmlResult(resource, StatusCodes.Status200OK); - } - - /// - /// Gets an that when executed will produce a response with given - /// and . - /// - /// The requested XML-formatted content of the response. - /// The HTTP status code of the response. - /// - /// An that when executed will produce a response with given - /// and . - /// - protected virtual ContentResult GetXmlResult(string content, int statusCode) - { - return new ContentResult - { - Content = content, - ContentType = "application/xml", - StatusCode = statusCode, - }; - } - - /// - /// Gets the string content of the resource. - /// - /// - /// Name of a manifest resource in the assembly containing . - /// - /// - /// A that on completion provides the content of the - /// resource. - /// - protected virtual async Task GetResourceAsync(string resourceName) - { - var assembly = typeof(SalesforceResultCreator).Assembly; - var content = assembly.GetManifestResourceStream(resourceName); - if (content == null) - { - var assemblyName = assembly.GetName().Name; - _logger.LogCritical( - 3, - "No '{0}' embedded resource found in the '{1}' assembly.", - resourceName, - assemblyName); - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.ResultCreator_MissingResource, - resourceName, - assemblyName); - throw new InvalidOperationException(message); - } - - using (var reader = new StreamReader(content)) - { - return await reader.ReadToEndAsync(); - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Internal/SalesforceServiceCollectionSetup.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Internal/SalesforceServiceCollectionSetup.cs deleted file mode 100644 index 6f23d4f..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Internal/SalesforceServiceCollectionSetup.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Internal; -using Microsoft.AspNetCore.WebHooks.Filters; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.AspNetCore.WebHooks.ModelBinding; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; - -namespace Microsoft.AspNetCore.WebHooks.Internal -{ - /// - /// Methods to add services for the Salesforce receiver. - /// - public static class SalesforceServiceCollectionSetup - { - /// - /// Add services for the Salesforce receiver. - /// - /// The to update. - public static void AddSalesforceServices(IServiceCollection services) - { - if (services == null) - { - throw new ArgumentNullException(nameof(services)); - } - - services.TryAddEnumerable(ServiceDescriptor.Transient, MvcOptionsSetup>()); - services.TryAddEnumerable(ServiceDescriptor.Singleton()); - services.TryAddSingleton(); - - services.TryAddSingleton(); - } - - private class MvcOptionsSetup : IConfigureOptions - { - private readonly ILoggerFactory _loggerFactory; - private readonly IHttpRequestStreamReaderFactory _readerFactory; - - public MvcOptionsSetup(ILoggerFactory loggerFactory, IHttpRequestStreamReaderFactory readerFactory) - { - _loggerFactory = loggerFactory; - _readerFactory = readerFactory; - } - - public void Configure(MvcOptions options) - { - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } - - // Ensure this binder is placed before the BodyModelBinderProvider, the most likely provider to match - // the XElement type. - var provider = new SalesforceNotificationsModelBinderProvider(_loggerFactory, options, _readerFactory); - options.ModelBinderProviders.Insert(0, provider); - - options.Filters.AddService(WebHookSecurityFilter.Order); - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Messages/FaultResponse.xml b/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Messages/FaultResponse.xml deleted file mode 100644 index af1be5c..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Messages/FaultResponse.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - soapenv:Client - {0} - - - - diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Messages/NotificationResponse.xml b/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Messages/NotificationResponse.xml deleted file mode 100644 index 14d66ad..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Messages/NotificationResponse.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - true - - - diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Metadata/SalesforceMetadata.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Metadata/SalesforceMetadata.cs deleted file mode 100644 index e318804..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Metadata/SalesforceMetadata.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// An service containing metadata about the Salesforce receiver. - /// - public class SalesforceMetadata : WebHookMetadata, IWebHookBodyTypeMetadataService - { - /// - /// Instantiates a new instance. - /// - public SalesforceMetadata() - : base(SalesforceConstants.ReceiverName) - { - } - - /// - public WebHookBodyType BodyType => WebHookBodyType.Xml; - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce.csproj b/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce.csproj deleted file mode 100644 index 7b84434..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - $(Configurations);CodeAnalysis - ASP.NET Core Salesforce WebHooks infrastructure. Contains the SalesforceWebHookAttribute class and AddSalesforceWebHooks method. - aspnetcore;webhook;receiver;salesforce - - - - - - Utilities\ObjectPathUtilities.cs - - - - - diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/ModelBinding/SalesforceNotificationsModelBinder.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/ModelBinding/SalesforceNotificationsModelBinder.cs deleted file mode 100644 index 261b006..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/ModelBinding/SalesforceNotificationsModelBinder.cs +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Threading.Tasks; -using System.Xml.Linq; -using Microsoft.AspNetCore.Mvc.ModelBinding; - -namespace Microsoft.AspNetCore.WebHooks.ModelBinding -{ - /// - /// An for instances. - /// - public class SalesforceNotificationsModelBinder : IModelBinder - { - private readonly IModelBinder _bodyModelBinder; - - /// - /// Instantiates a new instance. - /// - /// The to bind models from the request body. - public SalesforceNotificationsModelBinder(IModelBinder bodyModelBinder) - { - if (bodyModelBinder == null) - { - throw new ArgumentNullException(nameof(bodyModelBinder)); - } - - _bodyModelBinder = bodyModelBinder; - } - - /// - public async Task BindModelAsync(ModelBindingContext bindingContext) - { - if (bindingContext == null) - { - throw new ArgumentNullException(nameof(bindingContext)); - } - - // Try to get the XElement. - ModelBindingResult result; - var xElementMetadata = bindingContext.ModelMetadata.GetMetadataForType(typeof(XElement)); - using (var innerContext = bindingContext.EnterNestedScope( - xElementMetadata, - bindingContext.FieldName, - bindingContext.ModelName, - bindingContext.Model)) - { - await _bodyModelBinder.BindModelAsync(bindingContext); - result = bindingContext.Result; - } - - // If we got the XElement, create the SalesforceNotifications instance and return that. - if (result.IsModelSet) - { - result = ModelBindingResult.Success(new SalesforceNotifications((XElement)result.Model)); - } - - bindingContext.Result = result; - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/ModelBinding/SalesforceNotificationsModelBinderProvider.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/ModelBinding/SalesforceNotificationsModelBinderProvider.cs deleted file mode 100644 index 09b450c..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/ModelBinding/SalesforceNotificationsModelBinderProvider.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Internal; -using Microsoft.AspNetCore.Mvc.ModelBinding; -using Microsoft.AspNetCore.Mvc.ModelBinding.Binders; -using Microsoft.Extensions.Logging; - -namespace Microsoft.AspNetCore.WebHooks.ModelBinding -{ - /// - /// An for instances. - /// - public class SalesforceNotificationsModelBinderProvider : IModelBinderProvider - { - private readonly IModelBinder _bodyModelBinder; - - /// - /// Instantiates a new instance. - /// - /// The . - /// The . - /// The . - public SalesforceNotificationsModelBinderProvider( - ILoggerFactory loggerFactory, - MvcOptions options, - IHttpRequestStreamReaderFactory readerFactory) - { - _bodyModelBinder = new BodyModelBinder(options.InputFormatters, readerFactory, loggerFactory, options); - } - - /// - public IModelBinder GetBinder(ModelBinderProviderContext context) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (context.Metadata.ModelType == typeof(SalesforceNotifications)) - { - return new SalesforceNotificationsModelBinder(_bodyModelBinder); - } - - return null; - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Properties/Resources.Designer.cs deleted file mode 100644 index 7f94716..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Properties/Resources.Designer.cs +++ /dev/null @@ -1,90 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Microsoft.AspNetCore.WebHooks.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.AspNetCore.WebHooks.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to No '{0}' embedded resource found in the '{1}' assembly.. - /// - internal static string ResultCreator_MissingResource { - get { - return ResourceManager.GetString("ResultCreator_MissingResource", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The '{0}' value provided in the HTTP request body did not match the expected value.. - /// - internal static string VerifyOrganization_BadValue { - get { - return ResourceManager.GetString("VerifyOrganization_BadValue", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The HTTP request body did not contain a required '{0}' element.. - /// - internal static string VerifyOrganization_MissingValue { - get { - return ResourceManager.GetString("VerifyOrganization_MissingValue", resourceCulture); - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Properties/Resources.resx b/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Properties/Resources.resx deleted file mode 100644 index f786c87..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/Properties/Resources.resx +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - No '{0}' embedded resource found in the '{1}' assembly. - - - The '{0}' value provided in the HTTP request body did not match the expected value. - - - The HTTP request body did not contain a required '{0}' element. - - \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/SalesforceConstants.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/SalesforceConstants.cs deleted file mode 100644 index af92649..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/SalesforceConstants.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Well-known names used in Salesforce receivers and handlers. - /// - public static class SalesforceConstants - { - /// - /// Gets the XPath of the element in a Salesforce WebHook request body containing the event name. - /// - public static string EventNamePath => - "/*[local-name()='Body']/*[local-name()='notifications']/*[local-name()='ActionId']"; - - /// - /// Gets the XPath of the element in an Salesforce WebHook request body containing the Salesforce organization - /// identifier. - /// - public static string OrganizationIdPath => - "/*[local-name()='Body']/*[local-name()='notifications']/*[local-name()='OrganizationId']"; - - /// - /// Gets the name of the Salesforce WebHook receiver. - /// - public static string ReceiverName => "salesforce"; - - /// - /// Gets the minimum length of the secret key configured for this receiver. - /// - public static int SecretKeyMinLength => 15; - - /// - /// Gets the maximum length of the secret key configured for this receiver. - /// - public static int SecretKeyMaxLength => 18; - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/SalesforceNamespaces.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/SalesforceNamespaces.cs deleted file mode 100644 index a399cc1..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/SalesforceNamespaces.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Diagnostics.CodeAnalysis; -using System.Xml.Linq; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Common XML namespace URIs used by Salesforce SOAP messages. - /// - public static class SalesforceNamespaces - { - /// - /// The XML namespace URI identifying a SOAP envelope. - /// - [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "XNamespace is immutable.")] - public static readonly XNamespace Soap = "http://schemas.xmlsoap.org/soap/envelope/"; - - /// - /// The XML namespace URI identifying XSI information. - /// - [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "XNamespace is immutable.")] - public static readonly XNamespace Xsi = "http://www.w3.org/2001/XMLSchema-instance"; - - /// - /// The XML namespace URI identifying a Salesforce Outbound Message. - /// - [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "XNamespace is immutable.")] - public static readonly XNamespace OutboundMessage = "http://soap.sforce.com/2005/09/outbound"; - - /// - /// The XML namespace URI identifying Salesforce objects. - /// - [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "XNamespace is immutable.")] - public static readonly XNamespace Objects = "urn:sobject.enterprise.soap.sforce.com"; - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/SalesforceNotifications.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/SalesforceNotifications.cs deleted file mode 100644 index bd9e912..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/SalesforceNotifications.cs +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Xml.Linq; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Describes one or more event notifications received as an Outbound Message from Salesforce. - /// For details about Salesforce Outbound Messages, see https://go.microsoft.com/fwlink/?linkid=838587. - /// - public class SalesforceNotifications - { - private static readonly XNamespace Soap = SalesforceNamespaces.Soap; - private static readonly XNamespace Outbound = SalesforceNamespaces.OutboundMessage; - private static readonly XNamespace Xsi = SalesforceNamespaces.Xsi; - - private readonly XElement _doc; - - private string _organizationId; - private string _actionId; - private string _sessionId; - private string _enterpriseUrl; - private string _partnerUrl; - private List> _notifications; - - /// - /// Initializes a new instance of the with a given - /// representing an Outbound SOAP Message received from Salesforce. - /// - /// An Outbound SOAP Message received from Salesforce. - public SalesforceNotifications(XElement doc) - { - if (doc == null) - { - throw new ArgumentNullException(nameof(doc)); - } - _doc = doc; - } - - /// - /// Gets the complete Outbound SOAP Message received from Salesforce. - /// - public XElement Document - { - get - { - return _doc; - } - } - - /// - /// Gets the 18 character Organization ID originating this Outbound Message. - /// - public string OrganizationId - { - get - { - if (_organizationId == null) - { - _organizationId = GetNotificationsValueOrDefault("OrganizationId"); - } - return _organizationId; - } - } - - /// - /// Gets the Action ID for this Outbound Message. - /// The Action ID indicates the workflow rule (action) that triggers the message. - /// - public string ActionId - { - get - { - if (_actionId == null) - { - _actionId = GetNotificationsValueOrDefault("ActionId"); - } - return _actionId; - } - } - - /// - /// Gets the optional SessionID for this Outbound Message if included in the message. - /// A Session ID can be used to make subsequent calls back to Salesforce. - /// - public string SessionId - { - get - { - if (_sessionId == null) - { - _sessionId = GetNotificationsValueOrDefault("SessionId"); - } - return _sessionId; - } - } - - /// - /// Gets the enterprise URI for this Outbound Message. This is the URI to use to make calls back to - /// Salesforce using the enterprise WSDL. - /// - [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "These are directly deserialized values.")] - public string EnterpriseUrl - { - get - { - if (_enterpriseUrl == null) - { - _enterpriseUrl = GetNotificationsValueOrDefault("EnterpriseUrl"); - } - return _enterpriseUrl; - } - } - - /// - /// Gets the partner URI for this Outbound Message. This is the URI to use to make calls back to - /// Salesforce using the partner WSDL. - /// - [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "These are directly deserialized values.")] - public string PartnerUrl - { - get - { - if (_partnerUrl == null) - { - _partnerUrl = GetNotificationsValueOrDefault("PartnerUrl"); - } - return _partnerUrl; - } - } - - /// - /// Gets the collection of notifications included in this Outbound Message. Each notification - /// is represented as a where TKey is a property - /// name and TValue is the value of that property. For each notification, the Notification ID - /// can be found using the key _NotificationId. Similarly, the type of notification can be found - /// using the key _NotificationType. - /// - public IEnumerable> Notifications - { - get - { - if (_notifications == null) - { - _notifications = _doc.Element(Soap + "Body").Element(Outbound + "notifications").Elements(Outbound + "Notification") - .Select(n => GetNotificationValues(n).ToDictionary(x => x.Name.LocalName, x => x.Value)) - .ToList(); - } - - return _notifications; - } - } - - internal static IEnumerable GetNotificationValues(XElement notification) - { - // Add the notification ID - var id = notification.Element(Outbound + "Id"); - var notificationIdName = Outbound + "_NotificationId"; - var notificationId = new XElement(notificationIdName) { Value = id.Value }; - yield return notificationId; - - // Add the notification type - var salesForceObject = notification.Element(Outbound + "sObject"); - var type = salesForceObject.Attribute(Xsi + "type"); - var notificationTypeName = Outbound + "_NotificationType"; - var notificationType = new XElement(notificationTypeName) { Value = GetLocalName(type.Value) }; - yield return notificationType; - - // Add notification properties - foreach (var e in salesForceObject.Elements()) - { - yield return e; - } - } - - internal static string GetLocalName(string qualified) - { - var index = qualified != null ? qualified.IndexOf(':') : -1; - var type = index > -1 ? qualified.Substring(index + 1) : qualified; - return type; - } - - private string GetNotificationsValueOrDefault(string property) - { - try - { - var value = _doc.Element(Soap + "Body").Element(Outbound + "notifications").Element(Outbound + property).Value; - return value; - } - catch - { - return string.Empty; - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/SalesforceWebHookAttribute.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/SalesforceWebHookAttribute.cs deleted file mode 100644 index 71b0be8..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Salesforce/SalesforceWebHookAttribute.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// - /// An indicating the associated action is a Salesforce WebHook endpoint. Specifies - /// the optional . Also adds a - /// for the action. - /// - /// - /// The signature of the action should be: - /// - /// Task{IActionResult} ActionName(string id, string @event, TData data, [FromServices] ISalesforceResultCreator resultCreator) - /// - /// or include the subset of parameters required. TData must be compatible with expected requests e.g. - /// or . The - /// helps to create SOAP responses. - /// - /// - /// An example Salesforce WebHook URI is 'https://{host}/api/webhooks/incoming/salesforce/{id}'. - /// See for additional details about Salesforce - /// WebHook requests. - /// - /// - /// - /// - /// If the application enables CORS in general (see the Microsoft.AspNetCore.Cors package), apply - /// DisableCorsAttribute to this action. If the application depends on the - /// Microsoft.AspNetCore.Mvc.ViewFeatures package, apply IgnoreAntiforgeryTokenAttribute to this - /// action. - /// - /// - /// should be used at most once per in a - /// WebHook application. - /// - /// - public class SalesforceWebHookAttribute : WebHookAttribute - { - /// - /// Instantiates a new indicating the associated action is a - /// Salesforce WebHook endpoint. - /// - public SalesforceWebHookAttribute() - : base(SalesforceConstants.ReceiverName) - { - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Extensions/SlackMvcBuilderExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Extensions/SlackMvcBuilderExtensions.cs deleted file mode 100644 index d809bbb..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Extensions/SlackMvcBuilderExtensions.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using Microsoft.AspNetCore.WebHooks.Internal; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up Slack WebHooks in an . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class SlackMvcBuilderExtensions - { - /// - /// - /// Add Slack WebHook configuration and services to the specified . See - /// for additional details about - /// Slack WebHook requests. - /// - /// - /// The 'WebHooks:Slack:SecretKey:default' configuration value contains the secret key for Slack WebHook - /// URIs of the form 'https://{host}/api/webhooks/incoming/slack'. - /// 'WebHooks:Slack:SecretKey:{id}' configuration values contain secret keys for Slack WebHook URIs of - /// the form 'https://{host}/api/webhooks/incoming/slack/{id}'. - /// - /// - /// The to configure. - /// The . - public static IMvcBuilder AddSlackWebHooks(this IMvcBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - SlackServiceCollectionSetup.AddSlackServices(builder.Services); - - return builder.AddWebHooks(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Extensions/SlackMvcCoreBuilderExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Extensions/SlackMvcCoreBuilderExtensions.cs deleted file mode 100644 index 868a55b..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Extensions/SlackMvcCoreBuilderExtensions.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using Microsoft.AspNetCore.WebHooks.Internal; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up Slack WebHooks in an . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class SlackMvcCoreBuilderExtensions - { - /// - /// - /// Add Slack WebHook configuration and services to the specified . See - /// for additional details about - /// Slack WebHook requests. - /// - /// - /// The 'WebHooks:Slack:SecretKey:default' configuration value contains the secret key for Slack WebHook - /// URIs of the form 'https://{host}/api/webhooks/incoming/slack'. - /// 'WebHooks:Slack:SecretKey:{id}' configuration values contain secret keys for Slack WebHook URIs of - /// the form 'https://{host}/api/webhooks/incoming/slack/{id}'. - /// - /// - /// The to configure. - /// The . - public static IMvcCoreBuilder AddSlackWebHooks(this IMvcCoreBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - SlackServiceCollectionSetup.AddSlackServices(builder.Services); - - // While requests contain HTML form URL-encoded data, responses are JSON. - return builder - .AddJsonFormatters() - .AddWebHooks(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Filters/SlackVerifyTokenFilter.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Filters/SlackVerifyTokenFilter.cs deleted file mode 100644 index 1197c4e..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Filters/SlackVerifyTokenFilter.cs +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Globalization; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.WebHooks.Properties; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; - -namespace Microsoft.AspNetCore.WebHooks.Filters -{ - /// - /// An that verifies the Slack request body. Confirms the body deserializes as - /// an . Then confirms the token and event name are present in the data and that the - /// token matches the configured secret key. Adds a entry to the - /// in most cases. - /// - public class SlackVerifyTokenFilter : WebHookSecurityFilter, IAsyncResourceFilter, IWebHookReceiver - { - private readonly IWebHookRequestReader _requestReader; - - /// - /// Instantiates a new instance. - /// - /// - /// The used to initialize . - /// - /// - /// The used to initialize - /// . - /// - /// - /// The used to initialize . - /// - /// The . - public SlackVerifyTokenFilter( - IConfiguration configuration, - IHostingEnvironment hostingEnvironment, - ILoggerFactory loggerFactory, - IWebHookRequestReader requestReader) - : base(configuration, hostingEnvironment, loggerFactory) - { - _requestReader = requestReader; - } - - /// - public string ReceiverName => SlackConstants.ReceiverName; - - /// - public bool IsApplicable(string receiverName) - { - if (receiverName == null) - { - throw new ArgumentNullException(nameof(receiverName)); - } - - return string.Equals(ReceiverName, receiverName, StringComparison.OrdinalIgnoreCase); - } - - /// - public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - if (next == null) - { - throw new ArgumentNullException(nameof(next)); - } - - // 1. Confirm this filter applies. - var routeData = context.RouteData; - if (!routeData.TryGetWebHookReceiverName(out var receiverName) || !IsApplicable(receiverName)) - { - await next(); - return; - } - - // 2. Confirm we were reached using HTTPS. - var request = context.HttpContext.Request; - var errorResult = EnsureSecureConnection(receiverName, request); - if (errorResult != null) - { - context.Result = errorResult; - return; - } - - // 3. Get IFormCollection from the request body. - var data = await _requestReader.ReadAsFormDataAsync(context); - if (data == null) - { - // ReadAsFormDataAsync returns null only when other filters will log and return errors about the same - // conditions. Let those filters run. - await next(); - return; - } - - // 4. Ensure the token exists and matches the expected value. - string token = data[SlackConstants.TokenRequestFieldName]; - if (string.IsNullOrEmpty(token)) - { - Logger.LogError( - 0, - "The HTTP request body did not contain a required '{PropertyName}' property.", - SlackConstants.TokenRequestFieldName); - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.VerifyToken_MissingValue, - SlackConstants.TokenRequestFieldName); - context.Result = new BadRequestObjectResult(message); - - return; - } - - var secretKey = GetSecretKey( - ReceiverName, - routeData, - SlackConstants.SecretKeyMinLength, - SlackConstants.SecretKeyMaxLength); - - if (!SecretEqual(token, secretKey)) - { - Logger.LogError( - 1, - "The '{PropertyName}' value provided in the HTTP request body did not match the expected value.", - SlackConstants.TokenRequestFieldName); - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.VerifyToken_BadValue, - SlackConstants.TokenRequestFieldName); - context.Result = new BadRequestObjectResult(message); - - return; - } - - // 5. Get the event name and subtext. - string eventName = data[SlackConstants.TriggerRequestFieldName]; - if (eventName != null) - { - // Trigger was supplied. Remove the trigger word to get subtext. - string text = data[SlackConstants.TextRequestFieldName]; - routeData.Values[SlackConstants.SubtextRequestKeyName] = GetSubtext(eventName, text); - } - else if ((eventName = data[SlackConstants.CommandRequestFieldName]) != null) - { - // Command was supplied. No need to set subtext. - } - else - { - // Trigger and command were omitted. Set subtext to the full text (if any). - eventName = data[SlackConstants.TextRequestFieldName]; - routeData.Values[SlackConstants.SubtextRequestKeyName] = eventName; - } - - if (string.IsNullOrEmpty(eventName)) - { - Logger.LogError( - 2, - "The HTTP request body did not contain a required '{PropertyName1}', '{PropertyName2}', or " + - "'{PropertyName3}' property.", - SlackConstants.TriggerRequestFieldName, - SlackConstants.CommandRequestFieldName, - SlackConstants.TextRequestFieldName); - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.VerifyToken_MissingValues, - SlackConstants.TriggerRequestFieldName, - SlackConstants.CommandRequestFieldName, - SlackConstants.TextRequestFieldName); - context.Result = new BadRequestObjectResult(message); - - return; - } - - // 6. Success. Provide event name for model binding. - routeData.Values[WebHookConstants.EventKeyName] = eventName; - - await next(); - } - - /// - /// The 'text' parameter provided by Slack contains both the trigger and the rest of the phrase. This - /// isolates just the rest of the phrase making it easier to get in handlers. - /// - /// The word triggering this Slack WebHook - /// The full text containing the trigger word. - /// The subtext without the trigger word. - protected static string GetSubtext(string trigger, string text) - { - if (string.IsNullOrEmpty(text)) - { - return string.Empty; - } - - if (text.StartsWith(trigger, StringComparison.OrdinalIgnoreCase)) - { - return text.Substring(trigger.Length).Trim(); - } - - return text; - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Internal/SlackServiceCollectionSetup.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Internal/SlackServiceCollectionSetup.cs deleted file mode 100644 index 3cf7baa..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Internal/SlackServiceCollectionSetup.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.WebHooks.Filters; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Options; - -namespace Microsoft.AspNetCore.WebHooks.Internal -{ - /// - /// Methods to add services for the Slack receiver. - /// - public static class SlackServiceCollectionSetup - { - /// - /// Add services for the Slack receiver. - /// - /// The to update. - public static void AddSlackServices(IServiceCollection services) - { - if (services == null) - { - throw new ArgumentNullException(nameof(services)); - } - - services.TryAddEnumerable(ServiceDescriptor.Transient, MvcOptionsSetup>()); - services.TryAddEnumerable(ServiceDescriptor.Singleton()); - - services.TryAddSingleton(); - } - - private class MvcOptionsSetup : IConfigureOptions - { - /// - public void Configure(MvcOptions options) - { - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } - - options.Filters.AddService(WebHookSecurityFilter.Order); - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Metadata/SlackMetadata.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Metadata/SlackMetadata.cs deleted file mode 100644 index 6c276d2..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Metadata/SlackMetadata.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// An service containing metadata about the Slack receiver. - /// - public class SlackMetadata : WebHookMetadata, IWebHookBindingMetadata, IWebHookBodyTypeMetadataService - { - /// - /// Instantiates a new instance. - /// - public SlackMetadata() - : base(SlackConstants.ReceiverName) - { - } - - // IWebHookBindingMetadata... - - /// - public IReadOnlyList Parameters { get; } = new List - { - new WebHookParameter( - SlackConstants.SubtextParameterName, - WebHookParameterType.RouteValue, - SlackConstants.SubtextRequestKeyName, - isRequired: false), - }; - - // IWebHookBodyTypeMetadataService... - - /// - public WebHookBodyType BodyType => WebHookBodyType.Form; - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Microsoft.AspNetCore.WebHooks.Receivers.Slack.csproj b/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Microsoft.AspNetCore.WebHooks.Receivers.Slack.csproj deleted file mode 100644 index 2e457eb..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Microsoft.AspNetCore.WebHooks.Receivers.Slack.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - $(Configurations);CodeAnalysis - ASP.NET Core Slack WebHooks infrastructure. Contains the SlackWebHookAttribute class and AddSlackWebHooks method. - aspnetcore;webhook;receiver;slack - - - - - Utilities\TrimmingTokenizer.cs - - - - - diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Properties/Resources.Designer.cs deleted file mode 100644 index 94605b2..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Properties/Resources.Designer.cs +++ /dev/null @@ -1,126 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Microsoft.AspNetCore.WebHooks.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.AspNetCore.WebHooks.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to Unmatched quote ({0}) discovered at position {1}.. - /// - internal static string Command_ContainsUnmatchedQuote { - get { - return ResourceManager.GetString("Command_ContainsUnmatchedQuote", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Parameter name cannot contain ';' characters. Unexpected escape sequence ({0}) discovered at position {1}.. - /// - internal static string Command_NameInvalid { - get { - return ResourceManager.GetString("Command_NameInvalid", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Parameter name cannot be a quoted string. Unexpected character ({0}) discovered at position {1}.. - /// - internal static string Command_NameIsQuotedString { - get { - return ResourceManager.GetString("Command_NameIsQuotedString", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Parameter value contains text after a quoted string. Unexpected character ({0}) discovered at position {1}.. - /// - internal static string Command_ValueInvalid { - get { - return ResourceManager.GetString("Command_ValueInvalid", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The '{0}' value provided in the HTTP request body did not match the expected value.. - /// - internal static string VerifyToken_BadValue { - get { - return ResourceManager.GetString("VerifyToken_BadValue", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The HTTP request body did not contain a required '{0}' property.. - /// - internal static string VerifyToken_MissingValue { - get { - return ResourceManager.GetString("VerifyToken_MissingValue", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The HTTP request body did not contain a required '{0}', '{1}', or '{2}' property.. - /// - internal static string VerifyToken_MissingValues { - get { - return ResourceManager.GetString("VerifyToken_MissingValues", resourceCulture); - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Properties/Resources.resx b/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Properties/Resources.resx deleted file mode 100644 index f8bb6af..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/Properties/Resources.resx +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Unmatched quote ({0}) discovered at position {1}. - - - Parameter name cannot contain ';' characters. Unexpected escape sequence ({0}) discovered at position {1}. - - - Parameter name cannot be a quoted string. Unexpected character ({0}) discovered at position {1}. - - - Parameter value contains text after a quoted string. Unexpected character ({0}) discovered at position {1}. - - - The '{0}' value provided in the HTTP request body did not match the expected value. - - - The HTTP request body did not contain a required '{0}' property. - - - The HTTP request body did not contain a required '{0}', '{1}', or '{2}' property. - - \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackAttachment.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackAttachment.cs deleted file mode 100644 index d10f029..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackAttachment.cs +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.ObjectModel; -using Newtonsoft.Json; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// The is used to describe the contents of an . - /// - public class SlackAttachment - { - private readonly Collection _fields = new Collection(); - - private string _text; - private string _fallback; - - /// - /// Initializes a new instance of the class with the given - /// and . - /// - /// The main text in a message attachment. The text may contain Markdown-style formatting - /// as described in https://api.slack.com/docs/formatting. The contents will automatically be collapsed - /// if it contains more than 700 characters or more than 5 line breaks. In this case it will be displayed with - /// a "Show more..." link to the contents. - /// - /// A plain-text summary of the attachment which will be used in clients - /// that don't show formatted text (e.g. IRC, mobile notifications). It should not contain any markup. - public SlackAttachment(string text, string fallback) - { - if (text == null) - { - throw new ArgumentNullException(nameof(text)); - } - if (fallback == null) - { - throw new ArgumentNullException(nameof(fallback)); - } - _text = text; - _fallback = fallback; - } - - /// - /// Default constructor for serialization purposes - /// - internal SlackAttachment() - { - } - - /// - /// Gets or sets a required plain-text summary of the attachment. This text will be used in clients - /// that don't show formatted text (e.g. IRC, mobile notifications) and should not contain - /// any markup. - /// - [JsonProperty("fallback")] - public string Fallback - { - get - { - return _fallback; - } - set - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - _fallback = value; - } - } - - /// - /// Gets or sets an optional value that can either be one of good, warning, danger, - /// or any hex color code (e.g. #439FE0). This value is used to color the border along the left side - /// of the message attachment. - /// - [JsonProperty("color")] - public string Color { get; set; } - - /// - /// Gets or sets an optional text that appears above the message attachment block. - /// - [JsonProperty("pretext")] - public string Pretext { get; set; } - - /// - /// Gets or sets an optional small text used to display the author's name. - /// - [JsonProperty("author_name")] - public string AuthorName { get; set; } - - /// - /// Gets or sets a URI that will show up as a hyper link for the text. This will only be applied - /// if is present. - /// - [JsonProperty("author_link")] - public Uri AuthorLink { get; set; } - - /// - /// Gets or sets a URI that display a small 16x16 pixel image to the left of the text. This will only - /// be applied if is present. - /// - [JsonProperty("author_icon")] - public Uri AuthorIcon { get; set; } - - /// - /// Gets or sets an optional title which is displayed as larger, bold text near the top of a message attachment. - /// - [JsonProperty("title")] - public string Title { get; set; } - - /// - /// Gets or sets a hyper link for the text. This will only be applied if - /// is present. - /// - [JsonProperty("title_link")] - public Uri TitleLink { get; set; } - - /// - /// Gets or sets the main text in a message attachment. The text may contain Markdown-style formatting as described in https://api.slack.com/docs/formatting. - /// The contents will automatically be collapsed if it contains more than 700 characters or more than 5 line breaks. In this case it will be displayed with a - /// "Show more..." link to the contents. - /// - [JsonProperty("text")] - public string Text - { - get - { - return _text; - } - set - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - _text = value; - } - } - - /// - /// Gets or a URI to an image that will be displayed inside a message attachment. Currently supported formats include GIF, JPEG, PNG, and BMP. - /// - [JsonProperty("image_url")] - public Uri ImageLink { get; set; } - - /// - /// Gets or a URI to an image that will be displayed as a thumbnail on the right side of a message attachment. Currently supported formats - /// include GIF, JPEG, PNG, and BMP. - /// - [JsonProperty("thumb_url")] - public Uri ThumbLink { get; set; } - - /// - /// Gets a set of instances that will be displayed in a table inside the message attachment - /// - [JsonProperty("fields")] - public Collection Fields - { - get - { - return _fields; - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackCommand.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackCommand.cs deleted file mode 100644 index 1bb0bae..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackCommand.cs +++ /dev/null @@ -1,393 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Text; -using Microsoft.AspNetCore.WebHooks.Properties; -using Microsoft.AspNetCore.WebHooks.Utilities; -using Microsoft.Extensions.Primitives; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// The class provides mechanisms for parsing the text contained in - /// Slack slash commands and outgoing WebHooks following a variety of different formats enabling - /// different scenarios. - /// - public static class SlackCommand - { - private static readonly char[] LwsSeparator = new[] { ' ' }; - - /// - /// Parses the 'text' of a slash command or 'subtext' of an outgoing WebHook of the form 'action value'. - /// - /// - /// An example of an outgoing WebHook or slash command using this format is - /// '/assistant query what's the weather?' where '/assistant' is the trigger word or slash command, - /// 'query' is the action and 'what's the weather?' is the value. - /// - /// The 'text' of a slash command or 'subtext' of an outgoing WebHook. - /// - /// A mapping the action to its value. Both properties of the - /// will be when the - /// does not contain an action. The will - /// be when the contains no interior spaces i.e. the - /// action has no value. - /// - public static KeyValuePair ParseActionWithValue(string text) - { - if (string.IsNullOrEmpty(text)) - { - return new KeyValuePair(StringSegment.Empty, StringSegment.Empty); - } - - var values = new TrimmingTokenizer(text, LwsSeparator, maxCount: 2); - var enumerator = values.GetEnumerator(); - if (!enumerator.MoveNext()) - { - return new KeyValuePair(StringSegment.Empty, StringSegment.Empty); - } - - var action = enumerator.Current; - var value = enumerator.MoveNext() ? enumerator.Current : StringSegment.Empty; - - return new KeyValuePair(action, value); - } - - /// - /// Parses the parameters a slash command or of an outgoing WebHook of the form - /// 'action param1; param2=value2; param3=value 3; param4="quoted value4"; ...'. - /// Parameter values containing semi-colons can either escape the semi-colon using a backslash character, - /// i.e '\;', or quote the value using single quotes or double quotes. - /// - /// - /// An example of an outgoing WebHook or slash command using this format is - /// /appointment add title=doctor visit; time=Feb 3 2016 2 PM; location=Children's Hospital - /// where '/appointment' is the trigger word or slash command, 'add' is the action and title, time, and - /// location are parameters. In this case, caller would pass - /// title=doctor visit; time=Feb 3 2016 2 PM; location=Children's Hospital to this method. - /// - /// - /// The parameter portion of a slash command or an outgoing WebHook. Often the - /// from what - /// returned. - /// - /// - /// A in which one property is always . When successful, - /// Error is and Parameters an - /// mapping zero or more parameter names to zero or more values. Otherwise, Parameters is - /// and Error a describing the specific problem. - /// - public static (IDictionary> Parameters, string Error) ParseParameters( - StringSegment text) - { - var parameters = new Dictionary>( - StringSegmentComparer.OrdinalIgnoreCase); - var index = GetWhitespaceLength(text, initialIndex: 0); - while (index < text.Length) - { - var (length, name, error) = GetParameterName(text, index); - if (error != null) - { - return (Parameters: null, error); - } - - index += length; - - var equalsLength = GetEqualsLength(text, index); - index += equalsLength; - - var value = StringSegment.Empty; - if (equalsLength > 0) - { - (length, value, error) = GetParameterValue(text, index); - if (error != null) - { - return (Parameters: null, error); - } - - index += length; - } - - if (!(StringSegment.IsNullOrEmpty(name) && StringSegment.IsNullOrEmpty(value))) - { - if (!parameters.TryGetValue(name, out var list)) - { - list = new List(); - parameters.Add(name, list); - } - - list.Add(value); - } - - index += GetSemicolonLength(text, index); - } - - return (parameters, Error: null); - } - - /// - /// - /// Returns a normalized representation of the given . This method and - /// round-trip the semantics of the original text. - /// - /// - /// Does not preserve syntax such as whitespace in the passed to - /// , how parameter values were quoted, or the parameter order. - /// - /// - /// The mapping of parameter names to zero or more parameter values. - /// A normalized representation of the given . - public static string GetNormalizedParameterString(IDictionary> parameters) - { - if (parameters.Count == 0) - { - return string.Empty; - } - - var builder = new StringBuilder(); - var addSemicolon = false; - foreach (var parameter in parameters) - { - foreach (var parameterValue in parameter.Value) - { - if (addSemicolon) - { - builder.Append("; "); - } - - addSemicolon = true; - builder.Append(parameter.Key.Value); - if (StringSegment.IsNullOrEmpty(parameterValue)) - { - continue; - } - - builder.Append('='); - if (StringSegment.Equals(parameterValue, parameterValue.Trim(), StringComparison.Ordinal)) - { - // No leading or trailing whitespace. Escape semicolons in value using backslashes. - for (var i = 0; i < parameterValue.Length; i++) - { - var ch = parameterValue[i]; - if (ch == ';') - { - builder.Append('\\'); - } - - builder.Append(ch); - } - } - else if (parameterValue.IndexOf('\'') == -1) - { - // Need surrounding quotes and value does not contain single quotes. Use single quotes. - builder.Append('\''); - builder.Append(parameterValue.Value); - builder.Append('\''); - } - else - { - // Need quotes and value contains single quotes. Use double quotes. (No way to escape quotes.) - builder.Append('"'); - builder.Append(parameterValue.Value); - builder.Append('"'); - } - } - } - - return builder.ToString(); - } - - // Length is the number of characters required to reach equals separating a parameter name from its value, - // semicolon separating one parameter from another, or end of the given segment. - private static (int Length, StringSegment Value, string Error) GetParameterName( - StringSegment segment, - int initialIndex) - { - var index = initialIndex; - for (; index < segment.Length; index++) - { - // Names can be pretty much anything but must not contain quotes or an escaped backslash. Treated as - // StringSegment.Empty if only whitespace appears before the equals or semicolon. - var done = false; - switch (segment[index]) - { - case '\'': - case '"': - { - var error = string.Format( - CultureInfo.CurrentCulture, - Resources.Command_NameIsQuotedString, - segment[index], - index); - return (Length: 0, StringSegment.Empty, error); - } - - case '=': - case ';': - done = true; - break; - - case '\\': - if (index < segment.Length - 1 && segment[index + 1] == ';') - { - // An attempt to include a quoted semicolon in a name. Message refers to escape sequence. - var error = string.Format( - CultureInfo.CurrentCulture, - Resources.Command_NameInvalid, - segment.Substring(index, 2), - index); - return (Length: 0, StringSegment.Empty, error); - } - - // Nothing else to do: Backslashes just backslashes unless quoting semicolons outside a string. - break; - } - - if (done) - { - break; - } - } - - var name = segment.Subsegment(initialIndex, index - initialIndex).TrimEnd(); - - return (index - initialIndex, name, Error: null); - } - - // Return number of characters required to reach start of the parameter value, semicolon separating one - // parameter from another, or end of the given segment. - private static int GetEqualsLength(StringSegment segment, int initialIndex) - { - if (initialIndex >= segment.Length || segment[initialIndex] != '=') - { - return 0; - } - - return GetWhitespaceLength(segment, initialIndex + 1) + 1; - } - - // Return number of characters required to reach start of the next parameter or end of the given segment. - private static int GetSemicolonLength(StringSegment segment, int initialIndex) - { - if (initialIndex >= segment.Length || segment[initialIndex] != ';') - { - return 0; - } - - return GetWhitespaceLength(segment, initialIndex + 1) + 1; - } - - // Length is the number of characters required to reach semicolon separating one parameter from another - // or end of the given segment. - private static (int Length, StringSegment Value, string Error) GetParameterValue( - StringSegment segment, - int initialIndex) - { - if (initialIndex >= segment.Length) - { - return (Length: 0, StringSegment.Empty, Error: null); - } - - var firstChar = segment[initialIndex]; - if (firstChar == '\'' || firstChar == '"') - { - var quoteIndex = segment.IndexOf(firstChar, initialIndex + 1); - if (quoteIndex == -1) - { - var error = string.Format( - CultureInfo.CurrentCulture, - Resources.Command_ContainsUnmatchedQuote, - firstChar, - initialIndex); - return (Length: 0, StringSegment.Empty, error); - } - - var index = quoteIndex + 1; - index += GetWhitespaceLength(segment, index); - - if (index < segment.Length && segment[index] != ';') - { - // Found something other than whitespace before the next semicolon or the end of the segment. - var error = string.Format( - CultureInfo.CurrentCulture, - Resources.Command_ValueInvalid, - segment[index], - index); - return (Length: 0, StringSegment.Empty, error); - } - - var value = segment.Subsegment(initialIndex + 1, length: quoteIndex - initialIndex - 1); - return (index - initialIndex, value, Error: null); - } - - var (length, unquotedValue) = GetUnquotedValue(segment, initialIndex); - return (length, unquotedValue, Error: null); - } - - private static (int Length, StringSegment Value) GetUnquotedValue(StringSegment segment, int initialIndex) - { - var backslashesToRemove = 0; - var index = initialIndex; - for (; index < segment.Length; index++) - { - var done = false; - switch (segment[index]) - { - case ';': - done = true; - break; - - case '\\': - if (index < segment.Length - 1 && segment[index + 1] == ';') - { - backslashesToRemove++; - index++; - } - break; - } - - if (done) - { - break; - } - } - - var length = index - initialIndex; - StringSegment value; - if (backslashesToRemove == 0) - { - value = segment.Subsegment(initialIndex, length); - } - else - { - var builder = new StringBuilder(length - backslashesToRemove); - for (var i = initialIndex; i < index; i++) - { - // Append all characters except a backslash before a semicolon. - var ch = segment[i]; - if (!(ch == '\\' && i < index - 1 && segment[i + 1] == ';')) - { - builder.Append(ch); - } - } - - value = new StringSegment(builder.ToString()); - } - - return (length, value.TrimEnd()); - } - - private static int GetWhitespaceLength(StringSegment segment, int initialIndex) - { - var index = initialIndex; - for (; index < segment.Length && char.IsWhiteSpace(segment[index]); index++) - { - } - - return index - initialIndex; - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackConstants.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackConstants.cs deleted file mode 100644 index fa99163..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackConstants.cs +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Well-known names used in Slack receivers and handlers. - /// - public static class SlackConstants - { - /// - /// Gets the name of the posted value in a Slack WebHook request body containing the channel name. - /// - public static string ChannelRequestFieldName => "channel_name"; - - /// - /// Gets the name of the posted value in a Slack WebHook request body containing the command name. Value is - /// used as the event name when included in a request and is not. - /// - public static string CommandRequestFieldName => "command"; - - /// - /// Gets the name of the Slack WebHook receiver. - /// - public static string ReceiverName => "slack"; - - /// - /// Gets the minimum length of the secret key configured for this receiver. - /// - public static int SecretKeyMinLength => 16; - - /// - /// Gets the maximum length of the secret key configured for this receiver. - /// - public static int SecretKeyMaxLength => 128; - - /// - /// Gets the name of the entry containing the subtext - /// value for the current request. This entry contains the portion of the - /// value which does not match the value if - /// is non-. This entry contains the - /// value if both and - /// values are . Otherwise, the - /// will not contain this entry. - /// - public static string SubtextRequestKeyName => "subtext"; - - /// - /// Gets the name of a parameter bound to the Slack subtext value for the current request. - /// - /// - public static string SubtextParameterName => "subtext"; - - /// - /// Gets the name of the posted value in a Slack WebHook request body containing the text of the event. Value - /// is used as the event name when neither nor - /// is included in a request. - /// - public static string TextRequestFieldName => "text"; - - /// - /// Gets the name of the posted value in a Slack WebHook request body containing the shared-private security - /// token. - /// - public static string TokenRequestFieldName => "token"; - - /// - /// Gets the name of the posted value in a Slack WebHook request body containing the trigger word which caused - /// this event, if any. Value is used as the event name when included in a request. - /// - public static string TriggerRequestFieldName => "trigger_word"; - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackField.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackField.cs deleted file mode 100644 index e6d6f75..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackField.cs +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Newtonsoft.Json; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// The class is used for expression table fields as part of a , - /// please see https://api.slack.com/docs/attachments for details. Fields are displayed in a table inside the message - /// attachment. - /// - public class SlackField - { - private string _title; - private string _value; - - /// - /// Initializes a new instance of the with the given - /// and . - /// - /// The field title shown as a bold heading above the value text. It cannot contain markup and will be escaped - /// by the receiver. - /// The field value which may contain Markdown-style formatting as described in https://api.slack.com/docs/formatting. - /// The value may be multi-line and must be escaped following Markdown rules. - public SlackField(string title, string value) - { - if (title == null) - { - throw new ArgumentNullException(nameof(title)); - } - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - _title = title; - _value = value; - } - - /// - /// Default constructor for serialization purposes - /// - internal SlackField() - { - } - - /// - /// Gets or sets the field title shown as a bold heading above the value text. It cannot contain markup and will be escaped - /// by the receiver. - /// - [JsonProperty("title")] - public string Title - { - get - { - return _title; - } - set - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - _title = value; - } - } - - /// - /// Gets or sets the field value. It may contain Markdown-style formatting as described in https://api.slack.com/docs/formatting. - /// The value may be multi-line and must be escaped following Markdown rules. - /// - [JsonProperty("value")] - public string Value - { - get - { - return _value; - } - set - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - _value = value; - } - } - - /// - /// Gets or sets a value indicating whether the field is short enough to be displayed side-by-side with other fields. - /// - [JsonProperty("short")] - public bool Short { get; set; } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackResponse.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackResponse.cs deleted file mode 100644 index b3bb52b..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackResponse.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Newtonsoft.Json; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// An Slack WebHook action can post back a response to a Slack channel by returning a - /// or an with a as its content. - /// - public class SlackResponse - { - private string _text; - - /// - /// Initializes a new instance of the with a given text to post - /// to the Slack channel from which the WebHook were received. - /// - public SlackResponse(string text) - { - if (text == null) - { - throw new ArgumentNullException(nameof(text)); - } - _text = text; - } - - /// - /// Gets or sets the text to send to Slack in response to an incoming WebHook request. - /// - [JsonProperty("text")] - public string Text - { - get - { - return _text; - } - set - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - _text = value; - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackSlashResponse.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackSlashResponse.cs deleted file mode 100644 index 68e9147..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackSlashResponse.cs +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.ObjectModel; -using Newtonsoft.Json; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// An Slack WebHook action can post back a response to a Slack Slash request by returning a - /// or an with a - /// as its content. Please see for - /// additional details about Slack Slash messages. - /// - public class SlackSlashResponse - { - private readonly Collection _attachments = new Collection(); - - private string _text; - - /// - /// Initializes a new instance of the class with the given . - /// - /// The Slack Slash command response text. The text may contain Markdown-style formatting - /// as described in https://api.slack.com/docs/formatting. The contents will automatically be collapsed - /// if it contains more than 700 characters or more than 5 line breaks. In this case it will be displayed with - /// a "Show more..." link to the contents. - /// - public SlackSlashResponse(string text) - : this(text, new SlackAttachment[0]) - { - } - - /// - /// Initializes a new instance of the class with the given and - /// one or more instances for additional response information. Please see - /// for all the options available. - /// - /// The Slack Slash command response text. The text may contain Markdown-style formatting - /// as described in https://api.slack.com/docs/formatting. The contents will automatically be collapsed - /// if it contains more than 700 characters or more than 5 line breaks. In this case it will be displayed with - /// a "Show more..." link to the contents. - /// - /// One or more instances providing additional response information. - /// Please see for all the options available. - public SlackSlashResponse(string text, params SlackAttachment[] attachments) - { - if (text == null) - { - throw new ArgumentNullException(nameof(text)); - } - if (attachments == null) - { - throw new ArgumentNullException(nameof(attachments)); - } - - _text = text; - foreach (var att in attachments) - { - _attachments.Add(att); - } - } - - /// - /// Default constructor for serialization purposes - /// - internal SlackSlashResponse() - { - } - - /// - /// Gets or sets the Slack Slash Response text. - /// - [JsonProperty("text")] - public string Text - { - get - { - return _text; - } - set - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - _text = value; - } - } - - /// - /// Gets or sets the Slack Slash Response type. This value must be either in_channel or ephemeral. - /// If in_channel then both the response message and the initial message typed by the user will be shared in the channel. - /// If ephemeral (default) then the response message will be visible only to the user that issued the command. - /// - [JsonProperty("response_type")] - public string ResponseType { get; set; } - - /// - /// Gets a set of instances that will comprise the Slack Slash response. - /// - [JsonProperty("attachments")] - public Collection Attachments - { - get - { - return _attachments; - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackWebHookAttribute.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackWebHookAttribute.cs deleted file mode 100644 index a469ba3..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Slack/SlackWebHookAttribute.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.ApiExplorer; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.AspNetCore.Mvc.Formatters; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// - /// An indicating the associated action is a Slack WebHook endpoint. Specifies the optional - /// . Also adds a for the - /// action and delegates its implementations - /// to a , indicating the action produces JSON-formatted responses. - /// - /// - /// The signature of the action should be: - /// - /// Task{TResult} ActionName(string id, string @event, string subtext, TData data) - /// - /// or include the subset of parameters required. TData must be compatible with expected requests e.g. - /// . TResult may be , - /// , or an implementation. - /// - /// - /// An example Slack WebHook URI is 'https://{host}/api/webhooks/incoming/slack/{id}'. - /// See for additional details about - /// Slack WebHook requests. - /// - /// - /// - /// - /// If the application enables CORS in general (see the Microsoft.AspNetCore.Cors package), apply - /// DisableCorsAttribute to this action. If the application depends on the - /// Microsoft.AspNetCore.Mvc.ViewFeatures package, apply IgnoreAntiforgeryTokenAttribute to this - /// action. - /// - /// - /// should be used at most once per in a - /// WebHook application. - /// - /// - /// Implements to provide information to a . - /// Implements for the odd case where no applies. - /// - /// - public class SlackWebHookAttribute : WebHookAttribute, IResultFilter, IApiResponseMetadataProvider - { - private static readonly ProducesAttribute Produces = new ProducesAttribute("application/json"); - - /// - /// Instantiates a new indicating the associated action is a Slack WebHook - /// endpoint. - /// - public SlackWebHookAttribute() - : base(SlackConstants.ReceiverName) - { - } - - /// - Type IApiResponseMetadataProvider.Type => Produces.Type; - - /// - int IApiResponseMetadataProvider.StatusCode => Produces.StatusCode; - - /// - void IApiResponseMetadataProvider.SetContentTypes(MediaTypeCollection contentTypes) - => Produces.SetContentTypes(contentTypes); - - /// - void IResultFilter.OnResultExecuting(ResultExecutingContext context) => Produces.OnResultExecuting(context); - - /// - void IResultFilter.OnResultExecuted(ResultExecutedContext context) => Produces.OnResultExecuted(context); - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Extensions/StripeMvcBuilderExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Extensions/StripeMvcBuilderExtensions.cs deleted file mode 100644 index 8e1adeb..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Extensions/StripeMvcBuilderExtensions.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using Microsoft.AspNetCore.WebHooks.Internal; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up Stripe WebHooks in an . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class StripeMvcBuilderExtensions - { - /// - /// - /// Add Stripe WebHook configuration and services to the specified . See - /// for additional details about Stripe WebHook requests. See - /// for additional details about Stripe Connect WebHook - /// requests. And, see for additional details about - /// Stripe WebHook request payloads. - /// - /// - /// The 'WebHooks:Stripe:SecretKey:default' configuration value contains the signing secret for Stripe - /// WebHook URIs of the form 'https://{host}/api/webhooks/incoming/stripe'. - /// 'WebHooks:Stripe:SecretKey:{id}' configuration values contain signing secret for Stripe WebHook URIs - /// of the form 'https://{host}/api/webhooks/incoming/stripe/{id}'. For details about Stripe signing - /// secrets, see . - /// - /// - /// The to configure. - /// The . - public static IMvcBuilder AddStripeWebHooks(this IMvcBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - StripeServiceCollectionSetup.AddStripeServices(builder.Services); - - return builder.AddWebHooks(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Extensions/StripeMvcCoreBuilderExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Extensions/StripeMvcCoreBuilderExtensions.cs deleted file mode 100644 index c1bdf6c..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Extensions/StripeMvcCoreBuilderExtensions.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using Microsoft.AspNetCore.WebHooks.Internal; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up Stripe WebHooks in an . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class StripeMvcCoreBuilderExtensions - { - /// - /// - /// Add Stripe WebHook configuration and services to the specified . See - /// for additional details about Stripe WebHook requests. See - /// for additional details about Stripe Connect WebHook - /// requests. And, see for additional details about - /// Stripe WebHook request payloads. - /// - /// - /// The 'WebHooks:Stripe:SecretKey:default' configuration value contains the signing secret for Stripe - /// WebHook URIs of the form 'https://{host}/api/webhooks/incoming/stripe'. - /// 'WebHooks:Stripe:SecretKey:{id}' configuration values contain signing secret for Stripe WebHook URIs - /// of the form 'https://{host}/api/webhooks/incoming/stripe/{id}'. For details about Stripe signing - /// secrets, see . - /// - /// - /// The to configure. - /// The . - public static IMvcCoreBuilder AddStripeWebHooks(this IMvcCoreBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - StripeServiceCollectionSetup.AddStripeServices(builder.Services); - - return builder - .AddJsonFormatters() - .AddWebHooks(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Filters/StripeTestEventRequestFilter.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Filters/StripeTestEventRequestFilter.cs deleted file mode 100644 index 6992662..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Filters/StripeTestEventRequestFilter.cs +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.AspNetCore.Routing; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; - -namespace Microsoft.AspNetCore.WebHooks.Filters -{ - /// - /// An that logs about and optionally short-circuits Stripe test events. Does not - /// short-circuit test events when the WebHooks:Stripe:PassThroughTestEvents configuration value is - /// true. - /// - /// Somewhat similar to the . - public class StripeTestEventRequestFilter : IResourceFilter, IWebHookReceiver - { - private readonly IConfiguration _configuration; - private readonly ILogger _logger; - - /// - /// Instantiates a new instance. - /// - /// The . - /// The . - public StripeTestEventRequestFilter(IConfiguration configuration, ILoggerFactory loggerFactory) - { - _configuration = configuration; - _logger = loggerFactory.CreateLogger(); - } - - /// - public string ReceiverName => StripeConstants.ReceiverName; - - /// - /// Gets the recommended for all - /// instances. This filter should execute in the same slot as . - /// does not apply for this receiver. - /// - public static int Order => WebHookPingRequestFilter.Order; - - /// - public bool IsApplicable(string receiverName) - { - if (receiverName == null) - { - throw new ArgumentNullException(nameof(receiverName)); - } - - return string.Equals(ReceiverName, receiverName, StringComparison.OrdinalIgnoreCase); - } - - /// - public void OnResourceExecuting(ResourceExecutingContext context) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var routeData = context.RouteData; - if (!routeData.TryGetWebHookReceiverName(out var receiverName) || !IsApplicable(receiverName)) - { - return; - } - - var notificationId = (string)routeData.Values[StripeConstants.NotificationIdKeyName]; - if (IsTestEvent(notificationId)) - { - // Log about and optionally short-circuit this test event. - var passThroughString = _configuration[StripeConstants.PassThroughTestEventsConfigurationKey]; - if (bool.TryParse(passThroughString, out var passThrough) && passThrough) - { - _logger.LogInformation(0, "Received a Stripe Test Event."); - } - else - { - _logger.LogInformation(1, "Ignoring a Stripe Test Event."); - context.Result = new OkResult(); - } - } - } - - /// - public void OnResourceExecuted(ResourceExecutedContext context) - { - // No-op - } - - internal static bool IsTestEvent(string notificationId) - { - return string.Equals( - StripeConstants.TestNotificationId, - notificationId, - StringComparison.OrdinalIgnoreCase); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Filters/StripeVerifyNotificationIdFilter.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Filters/StripeVerifyNotificationIdFilter.cs deleted file mode 100644 index 8a4b9be..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Filters/StripeVerifyNotificationIdFilter.cs +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Globalization; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.WebHooks.Properties; -using Microsoft.Extensions.Logging; -using Newtonsoft.Json.Linq; - -namespace Microsoft.AspNetCore.WebHooks.Filters -{ - /// - /// An that verifies the Stripe request body. Confirms the body deserializes as - /// a . Confirms notification identifier and event name are present. Adds both strings to - /// route values. - /// - public class StripeVerifyNotificationIdFilter : IAsyncResourceFilter, IWebHookReceiver - { - private readonly ILogger _logger; - private readonly IWebHookRequestReader _requestReader; - - /// - /// Instantiates a new instance. - /// - /// The . - /// The . - public StripeVerifyNotificationIdFilter(ILoggerFactory loggerFactory, IWebHookRequestReader requestReader) - { - _logger = loggerFactory.CreateLogger(); - _requestReader = requestReader; - } - - /// - /// Gets the recommended for all - /// instances. This filter should execute in the same slot as - /// , after and before - /// . does not apply - /// for this receiver; required parameters are enforced in this filter. - /// - public static int Order => WebHookVerifyRequiredValueFilter.Order; - - /// - public string ReceiverName => StripeConstants.ReceiverName; - - /// - public bool IsApplicable(string receiverName) - { - if (receiverName == null) - { - throw new ArgumentNullException(nameof(receiverName)); - } - - return string.Equals(ReceiverName, receiverName, StringComparison.OrdinalIgnoreCase); - } - - /// - public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - if (next == null) - { - throw new ArgumentNullException(nameof(next)); - } - - // 1. Confirm this filter applies. - var routeData = context.RouteData; - if (!routeData.TryGetWebHookReceiverName(out var receiverName) || !IsApplicable(receiverName)) - { - await next(); - return; - } - - // 2. Get JObject from the request body. - var data = await _requestReader.ReadBodyAsync(context); - if (data == null) - { - var modelState = context.ModelState; - if (modelState.IsValid) - { - // ReadAsJObjectAsync returns null when model state is valid only when other filters will log and - // return errors about the same conditions. Let those filters run. - await next(); - } - else - { - context.Result = new BadRequestObjectResult(modelState); - } - - return; - } - - // 3. Ensure the notification identifier exists. - var notificationId = data.Value(StripeConstants.NotificationIdPropertyName); - if (string.IsNullOrEmpty(notificationId)) - { - _logger.LogError( - 0, - "The HTTP request body did not contain a required '{PropertyName}' property.", - StripeConstants.NotificationIdPropertyName); - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.VerifyNotification_MissingValue, - StripeConstants.NotificationIdPropertyName); - context.Result = new BadRequestObjectResult(message); - - return; - } - - // 4. Ensure the event name exists. - var eventName = data.Value(StripeConstants.EventPropertyName); - if (string.IsNullOrEmpty(eventName)) - { - _logger.LogError( - 1, - "The HTTP request body did not contain a required '{PropertyName}' property.", - StripeConstants.EventPropertyName); - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.VerifyNotification_MissingValue, - StripeConstants.EventPropertyName); - context.Result = new BadRequestObjectResult(message); - - return; - } - - // 5. Success. Provide event name and notification id for model binding. - routeData.Values[WebHookConstants.EventKeyName] = eventName; - routeData.Values[StripeConstants.NotificationIdKeyName] = notificationId; - - await next(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Filters/StripeVerifySignatureFilter.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Filters/StripeVerifySignatureFilter.cs deleted file mode 100644 index 6a68bcc..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Filters/StripeVerifySignatureFilter.cs +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Text; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.WebHooks.Properties; -using Microsoft.AspNetCore.WebHooks.Utilities; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Primitives; - -namespace Microsoft.AspNetCore.WebHooks.Filters -{ - /// - /// An that verifies the Stripe signature header. Confirms the header exists, - /// parses the header, reads Body bytes, and compares the hashes. - /// - public class StripeVerifySignatureFilter : WebHookVerifySignatureFilter, IAsyncResourceFilter - { - private static readonly char[] CommaSeparator = new[] { ',' }; - private static readonly char[] EqualSeparator = new[] { '=' }; - - /// - /// Instantiates a new instance. - /// - /// - /// The used to initialize . - /// - /// - /// The used to initialize - /// . - /// - /// - /// The used to initialize . - /// - public StripeVerifySignatureFilter( - IConfiguration configuration, - IHostingEnvironment hostingEnvironment, - ILoggerFactory loggerFactory) - : base(configuration, hostingEnvironment, loggerFactory) - { - } - - /// - public override string ReceiverName => StripeConstants.ReceiverName; - - /// - public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - if (next == null) - { - throw new ArgumentNullException(nameof(next)); - } - - // 1. Confirm this filter applies. - var routeData = context.RouteData; - var request = context.HttpContext.Request; - if (!routeData.TryGetWebHookReceiverName(out var receiverName) || - !IsApplicable(receiverName) || - !HttpMethods.IsPost(request.Method)) - { - await next(); - return; - } - - // 2. Confirm a secure connection. - var errorResult = EnsureSecureConnection(ReceiverName, request); - if (errorResult != null) - { - context.Result = errorResult; - return; - } - - // 3. Get the timestamp and expected signature(s) from the signature header. - var header = GetRequestHeader(request, StripeConstants.SignatureHeaderName, out errorResult); - if (errorResult != null) - { - context.Result = errorResult; - return; - } - - errorResult = ValidateHeader(header); - if (errorResult != null) - { - context.Result = errorResult; - return; - } - - var timestamp = GetTimestamp(header); - var signatures = GetSignatures(header); - - // 4. Get the configured secret key. - var secretKey = GetSecretKey( - ReceiverName, - routeData, - StripeConstants.SecretKeyMinLength, - StripeConstants.SecretKeyMaxLength); - if (secretKey == null) - { - context.Result = new NotFoundResult(); - return; - } - - var secret = Encoding.UTF8.GetBytes(secretKey); - var prefix = Encoding.UTF8.GetBytes(timestamp + "."); - - // 5. Get the actual hash of the request body. - var actualHash = await GetRequestBodyHash_SHA256(request, secret, prefix); - - // 6. Verify that the actual hash matches one of the expected hashes. - var match = false; - foreach (var signature in signatures) - { - // While this looks repetitious compared to hex-encoding actualHash (once), a single v1 entry in the - // header is the normal case. Expect multiple signatures only when rolling secret keys. - var expectedHash = GetDecodedHash( - signature.Value, - StripeConstants.SignatureHeaderName, - out errorResult); - if (errorResult != null) - { - context.Result = errorResult; - return; - } - - if (SecretEqual(expectedHash, actualHash)) - { - match = true; - break; - } - } - - if (!match) - { - // Log about the issue and short-circuit remainder of the pipeline. - context.Result = CreateBadSignatureResult(ReceiverName, StripeConstants.SignatureHeaderName); - return; - } - - // Success - await next(); - } - - // Header contains a comma-separated collection of key / value pairs. Get the value for the "t" key. - private StringSegment GetTimestamp(string header) - { - var pairs = new TrimmingTokenizer(header, CommaSeparator); - foreach (var pair in pairs) - { - var keyValuePair = new TrimmingTokenizer(pair, EqualSeparator, maxCount: 2); - var enumerator = keyValuePair.GetEnumerator(); - enumerator.MoveNext(); - if (StringSegment.Equals(enumerator.Current, StripeConstants.TimestampKey, StringComparison.Ordinal)) - { - enumerator.MoveNext(); - return enumerator.Current; - } - } - - return StringSegment.Empty; - } - - // Header contains a comma-separated collection of key / value pairs. Get all values for the "v1" key. - private IEnumerable GetSignatures(string header) - { - var pairs = new TrimmingTokenizer(header, CommaSeparator); - foreach (var pair in pairs) - { - var keyValuePair = new TrimmingTokenizer(pair, EqualSeparator, maxCount: 2); - var enumerator = keyValuePair.GetEnumerator(); - enumerator.MoveNext(); - if (StringSegment.Equals(enumerator.Current, StripeConstants.SignatureKey, StringComparison.Ordinal)) - { - enumerator.MoveNext(); - yield return enumerator.Current; - } - } - } - - private IActionResult ValidateHeader(string header) - { - var hasTimestamp = false; - var hasSignature = false; - var pairs = new TrimmingTokenizer(header, CommaSeparator); - foreach (var pair in pairs) - { - var keyValuePair = new TrimmingTokenizer(pair, EqualSeparator, maxCount: 2); - if (keyValuePair.Count != 2) - { - // Header is not formatted correctly. - Logger.LogError( - 2, - "The '{HeaderName}' header value is invalid. '{InvalidPair}' should be a 'key=value' pair.", - StripeConstants.SignatureHeaderName, - pair); - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.SignatureFilter_InvalidHeaderFormat, - StripeConstants.SignatureHeaderName); - return new BadRequestObjectResult(message); - } - - var enumerator = keyValuePair.GetEnumerator(); - enumerator.MoveNext(); - - var key = enumerator.Current; - if (StringSegment.Equals(key, StripeConstants.SignatureKey, StringComparison.Ordinal)) - { - enumerator.MoveNext(); - hasSignature = !StringSegment.IsNullOrEmpty(enumerator.Current); - } - else if (StringSegment.Equals(key, StripeConstants.TimestampKey, StringComparison.Ordinal)) - { - enumerator.MoveNext(); - hasTimestamp = !StringSegment.IsNullOrEmpty(enumerator.Current); - } - } - - if (!hasSignature) - { - Logger.LogError( - 3, - "The '{HeaderName}' header value is invalid. Does not contain a timestamp ('{Key}') value.", - StripeConstants.SignatureHeaderName, - StripeConstants.SignatureKey); - } - - if (!hasTimestamp) - { - Logger.LogError( - 4, - "The '{HeaderName}' header value is invalid. Does not contain a signature ('{Key}') value.", - StripeConstants.SignatureHeaderName, - StripeConstants.TimestampKey); - } - - if (!hasSignature || !hasTimestamp) - { - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.SignatureFilter_HeaderMissingValue, - StripeConstants.SignatureHeaderName, - StripeConstants.TimestampKey, - StripeConstants.SignatureKey); - return new BadRequestObjectResult(message); - } - - // Success - return null; - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Internal/StripeServiceCollectionSetup.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Internal/StripeServiceCollectionSetup.cs deleted file mode 100644 index eb7e497..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Internal/StripeServiceCollectionSetup.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.WebHooks.Filters; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Options; - -namespace Microsoft.AspNetCore.WebHooks.Internal -{ - /// - /// Methods to add services for the Stripe receiver. - /// - public static class StripeServiceCollectionSetup - { - /// - /// Add services for the Stripe receiver. - /// - /// The to update. - public static void AddStripeServices(IServiceCollection services) - { - if (services == null) - { - throw new ArgumentNullException(nameof(services)); - } - - services.TryAddEnumerable(ServiceDescriptor.Transient, MvcOptionsSetup>()); - services.TryAddEnumerable(ServiceDescriptor.Singleton()); - - services.TryAddSingleton(); - services.TryAddSingleton(); - services.TryAddSingleton(); - } - - private class MvcOptionsSetup : IConfigureOptions - { - /// - public void Configure(MvcOptions options) - { - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } - - var filters = options.Filters; - filters.AddService(StripeTestEventRequestFilter.Order); - filters.AddService(StripeVerifyNotificationIdFilter.Order); - filters.AddService(WebHookSecurityFilter.Order); - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Metadata/StripeMetadata.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Metadata/StripeMetadata.cs deleted file mode 100644 index d1ab992..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Metadata/StripeMetadata.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// An service containing metadata about the Stripe receiver. - /// - public class StripeMetadata : WebHookMetadata, IWebHookBindingMetadata, IWebHookBodyTypeMetadataService - { - /// - /// Instantiates a new instance. - /// - public StripeMetadata() - : base(StripeConstants.ReceiverName) - { - } - - // IWebHookBindingMetadata... - - /// - public IReadOnlyList Parameters { get; } = new List - { - new WebHookParameter( - StripeConstants.NotificationIdParameterName, - WebHookParameterType.RouteValue, - StripeConstants.NotificationIdKeyName, - isRequired: false), - }; - - // IWebHookBodyTypeMetadataService... - - /// - public WebHookBodyType BodyType => WebHookBodyType.Json; - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Microsoft.AspNetCore.WebHooks.Receivers.Stripe.csproj b/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Microsoft.AspNetCore.WebHooks.Receivers.Stripe.csproj deleted file mode 100644 index c9f1c3f..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Microsoft.AspNetCore.WebHooks.Receivers.Stripe.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - $(Configurations);CodeAnalysis - ASP.NET Core Stripe WebHooks infrastructure. Contains the StripeWebHookAttribute class and AddStripeWebHooks method. - aspnetcore;webhook;receiver;stripe - - - - - Utilities\TrimmingTokenizer.cs - - - - - diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/ModelBinding/UnixTimeConverter.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/ModelBinding/UnixTimeConverter.cs deleted file mode 100644 index 1a8932b..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/ModelBinding/UnixTimeConverter.cs +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Globalization; -using Microsoft.AspNetCore.WebHooks.Properties; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; - -namespace Microsoft.AspNetCore.WebHooks.ModelBinding -{ - /// - /// Converts a Unix time stamp string or integer value to and from a . By default, the - /// gets serialized to an integer. - /// - public class UnixTimeConverter : DateTimeConverterBase - { - private static readonly DateTime _Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); - private readonly bool _stringConverter; - - /// - /// Instantiates a new instance. - /// - public UnixTimeConverter() - : this(false) - { - } - - /// - /// Instantiates a new instance. - /// - /// - /// When only deserializes string values and serializes to a string value; - /// otherwise deserializes string and integer values and serializes to an integer value. - /// - protected UnixTimeConverter(bool stringConverter) - { - _stringConverter = stringConverter; - } - - /// - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - if (writer == null) - { - throw new ArgumentNullException(nameof(writer)); - } - - var utc = ((DateTime)value).ToUniversalTime(); - var time = (long)(utc - _Epoch).TotalSeconds; - if (_stringConverter) - { - writer.WriteValue(time.ToString(CultureInfo.InvariantCulture)); - } - else - { - writer.WriteValue(time); - } - } - - /// - public override object ReadJson( - JsonReader reader, - Type objectType, - object existingValue, - JsonSerializer serializer) - { - if (reader == null) - { - throw new ArgumentNullException(nameof(reader)); - } - if (reader.Value == null) - { - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.DateTime_NullError, - nameof(DateTime)); - throw new InvalidOperationException(message); - } - - long time = 0; - if (reader.TokenType == JsonToken.String || _stringConverter) - { - if (!long.TryParse(reader.Value as string, out time)) - { - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.DateTime_BadFormat, - reader.Value, - nameof(DateTime)); - throw new InvalidOperationException(message); - } - } - else if (reader.TokenType == JsonToken.Integer) - { - time = Convert.ToInt64(reader.Value, CultureInfo.InvariantCulture); - } - else - { - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.DateTime_BadFormat, - reader.Value, - nameof(DateTime)); - throw new InvalidOperationException(message); - } - - var utc = _Epoch.AddSeconds(time); - return utc; - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Properties/Resources.Designer.cs deleted file mode 100644 index b60e726..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Properties/Resources.Designer.cs +++ /dev/null @@ -1,108 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Microsoft.AspNetCore.WebHooks.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.AspNetCore.WebHooks.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to Cannot read value '{0}' as type '{1}'.. - /// - internal static string DateTime_BadFormat { - get { - return ResourceManager.GetString("DateTime_BadFormat", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot convert null value to type '{0}'.. - /// - internal static string DateTime_NullError { - get { - return ResourceManager.GetString("DateTime_NullError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The '{0}' header value is invalid. It must contain timestamp ('{1}') and signature ('{2}') values.. - /// - internal static string SignatureFilter_HeaderMissingValue { - get { - return ResourceManager.GetString("SignatureFilter_HeaderMissingValue", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The '{0}' header value is invalid. It must be formatted as key=value pairs separated by commas.. - /// - internal static string SignatureFilter_InvalidHeaderFormat { - get { - return ResourceManager.GetString("SignatureFilter_InvalidHeaderFormat", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The HTTP request body did not contain a required '{0}' property.. - /// - internal static string VerifyNotification_MissingValue { - get { - return ResourceManager.GetString("VerifyNotification_MissingValue", resourceCulture); - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Properties/Resources.resx b/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Properties/Resources.resx deleted file mode 100644 index 6a85151..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/Properties/Resources.resx +++ /dev/null @@ -1,135 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Cannot read value '{0}' as type '{1}'. - - - Cannot convert null value to type '{0}'. - - - The '{0}' header value is invalid. It must contain timestamp ('{1}') and signature ('{2}') values. - - - The '{0}' header value is invalid. It must be formatted as key=value pairs separated by commas. - - - The HTTP request body did not contain a required '{0}' property. - - \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/StripeConstants.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/StripeConstants.cs deleted file mode 100644 index 3627f7a..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/StripeConstants.cs +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.Extensions.Configuration; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Well-known names used in Stripe receivers and handlers. - /// - public static class StripeConstants - { - /// - /// Gets the name of the JSON property in a Stripe WebHook request body containing its Unix creation - /// timestamp. - /// - public static string CreatedPropertyName => "created"; - - - /// - /// Gets the name of the JSON property in a Stripe WebHook request body containing the - /// . - /// - public static string DataPropertyName => "data"; - - /// - /// Gets the name of the JSON property in a Stripe WebHook request body containing the event details. - /// - public static string DataDetailsPropertyName => "object"; - - /// - /// Gets the name of the JSON property in a Stripe WebHook request body containing the event name. - /// - public static string EventPropertyName => "type"; - - /// - /// Gets the name of the entry containing the Stripe - /// notification identifier for the current request. - /// - /// - public static string NotificationIdKeyName => "notificationId"; - - /// - /// Gets the name of a parameter bound to the Stripe notification identifier for the current request. - /// - /// - public static string NotificationIdParameterName => "notificationId"; - - /// - /// Gets the name of the JSON property in a Stripe WebHook request body containing the notification - /// identifier. - /// - public static string NotificationIdPropertyName => "id"; - - /// - /// Gets the name of the JSON property in a Stripe WebHook request body indicating it carries a live mode - /// event. - /// - /// if this is a live mode event; otherwise, this is a test mode event. - /// - /// Stripe sends test mode events i.e. uses test data with notification identifiers other than - /// . - /// - public static string LiveModePropertyName => "livemode"; - - /// - /// Gets the key of a configuration value indicating the Stripe receiver should flow test events to Stripe - /// actions. Configuration value, if any, should parse as a . If that parsed configuration - /// value is , the action will receive test events. Otherwise, the receiver - /// short-circuits test events. - /// - public static string PassThroughTestEventsConfigurationKey { get; } = ConfigurationPath.Combine( - WebHookConstants.ReceiverConfigurationSectionKey, - ReceiverName, - "PassThroughTestEvents"); - - /// - /// Gets the name of the Stripe WebHook receiver. - /// - public static string ReceiverName => "stripe"; - - /// - /// Gets the minimum length of the secret key configured for this receiver. - /// - public static int SecretKeyMinLength => 16; - - /// - /// Gets the maximum length of the secret key configured for this receiver. - /// - public static int SecretKeyMaxLength => 128; - - /// - /// Gets the name of the HTTP header that contains the timestamp and signature of the request. See - /// and - /// for more information about this header. - /// - public static string SignatureHeaderName => "Stripe-Signature"; - - /// - /// Gets the key of the signature value(s) in the . - /// - public static string SignatureKey => "v1"; - - /// - /// Gets the notification identifier used in test Stripe WebHook requests. - /// - /// - /// Stripe does not use this notification identifier when for example sending an event about a test payment. - /// - /// - public static string TestNotificationId => "evt_00000000000000"; - - /// - /// Gets the key of the timestamp value in the . - /// - public static string TimestampKey => "t"; - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/StripeEvent.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/StripeEvent.cs deleted file mode 100644 index 907bf9d..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/StripeEvent.cs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.WebHooks.ModelBinding; -using Newtonsoft.Json; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Contains information sent in a WebHook notification from Stripe, see - /// 'https://stripe.com/docs/api#event_object' for details. - /// - public class StripeEvent - { - /// - /// Gets or sets the id of the WebHook event - /// - [JsonProperty("id")] - public string Id { get; set; } - - /// - /// Gets or sets the object. Value is "event". - /// - [JsonProperty("object")] - public string Object { get; set; } - - /// - /// Gets or sets the Stripe API version used to render data. - /// Note: this property is populated for events on or after October 31, 2014. - /// - [JsonProperty("api_version")] - public string ApiVersion { get; set; } - - /// - /// Gets or sets the time at which the alert was triggered. - /// - [JsonConverter(typeof(UnixTimeConverter))] - [JsonProperty("created")] - public DateTime Created { get; set; } - - /// - /// Gets or sets the hash containing data associated with the event. - /// - [JsonProperty("data")] - public StripeEventData Data { get; set; } - - /// - /// Gets or sets the boolean property to denote if this is a live event or not. - /// - [JsonProperty("livemode")] - public bool LiveMode { get; set; } - - /// - /// Gets or sets the number of WebHooks yet to be delivered successfully - /// (return a 20x response) to the URLs you've specified. - /// - [JsonProperty("pending_webhooks")] - public int PendingWebHooks { get; set; } - - /// - /// Gets the ID of the API request that caused the event. - /// If null, the event was automatic (e.g. Stripe's automatic subscription handling). - /// Request logs are available in the dashboard but currently not in the API. - /// - [JsonIgnore] - public string Request => RequestData?.Id; - - /// - /// Gets or sets the details of the API request that caused the event. - /// - [JsonProperty("request")] - public StripeRequestData RequestData { get; set; } - - /// - /// Gets or sets the description of the event: e.g. invoice.created, charge.refunded, etc. - /// - [JsonProperty("type")] - public string EventType { get; set; } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/StripeEventData.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/StripeEventData.cs deleted file mode 100644 index 27dea1e..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/StripeEventData.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Diagnostics.CodeAnalysis; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Contains information sent in a WebHook notification from Stripe, see - /// 'https://stripe.com/docs/api#event_object' for details. - /// - public class StripeEventData - { - /// - /// Gets or sets the event data object. - /// - [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "The JObject has to be settable.")] - [JsonProperty("object")] - public JObject Object { get; set; } - - /// - /// Gets or sets the hash containing the names of the attributes that have changed - /// and their previous values (only sent along with *.updated events). - /// - [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "The JObject has to be settable.")] - [JsonProperty("previous_attributes")] - public JObject PreviousAttributes { get; set; } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/StripeRequestData.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/StripeRequestData.cs deleted file mode 100644 index 11b8e30..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/StripeRequestData.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Newtonsoft.Json; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Contains information sent in a WebHook notification from Stripe. Describes the API request that caused the - /// event. See for details. - /// - public class StripeRequestData - { - /// - /// Gets or sets the ID of the API request that caused the event. - /// - /// if the event was automatic. Otherwise, the API request ID. - [JsonProperty("id")] - public string Id { get; set; } - - /// - /// Gets or sets the idempotency key transmitted in the API request. - /// - /// This property is only populated for events on or after May 23, 2017. - [JsonProperty("idempotency_key")] - public string IdempotencyKey { get; set; } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/StripeWebHookAttribute.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/StripeWebHookAttribute.cs deleted file mode 100644 index d2070eb..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Stripe/StripeWebHookAttribute.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// - /// An indicating the associated action is a Stripe WebHook endpoint. Specifies the - /// optional . Also adds a for - /// the action. - /// - /// - /// The signature of the action should be: - /// - /// Task{IActionResult} ActionName(string id, string @event, string notificationId, TData data) - /// - /// or include the subset of parameters required. TData must be compatible with expected requests e.g. - /// or . - /// - /// - /// An example Stripe WebHook URI is 'https://{host}/api/webhooks/incoming/stripe/{id}'. See - /// for additional details about Stripe WebHook requests. See - /// for additional details about Stripe Connect WebHook - /// requests. And, see for additional details about Stripe - /// WebHook request payloads. - /// - /// - /// - /// - /// If the application enables CORS in general (see the Microsoft.AspNetCore.Cors package), apply - /// DisableCorsAttribute to this action. If the application depends on the - /// Microsoft.AspNetCore.Mvc.ViewFeatures package, apply IgnoreAntiforgeryTokenAttribute to this - /// action. - /// - /// - /// should be used at most once per in a - /// WebHook application. - /// - /// - public class StripeWebHookAttribute : WebHookAttribute - { - /// - /// Instantiates a new indicating the associated action is a Stripe - /// WebHook endpoint. - /// - public StripeWebHookAttribute() - : base(StripeConstants.ReceiverName) - { - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.Trello/Microsoft.AspNetCore.WebHooks.Receivers.Trello.csproj b/src/Microsoft.AspNetCore.WebHooks.Receivers.Trello/Microsoft.AspNetCore.WebHooks.Receivers.Trello.csproj deleted file mode 100644 index 4cf35ff..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.Trello/Microsoft.AspNetCore.WebHooks.Receivers.Trello.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - $(Configurations);CodeAnalysis - ASP.NET Core Trello WebHooks infrastructure. Contains the TrelloWebHookAttribute class and AddTrelloWebHooks method. - aspnetcore;webhook;receiver;trello - - - - - - diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers.WordPress/Microsoft.AspNetCore.WebHooks.Receivers.WordPress.csproj b/src/Microsoft.AspNetCore.WebHooks.Receivers.WordPress/Microsoft.AspNetCore.WebHooks.Receivers.WordPress.csproj deleted file mode 100644 index efddcfd..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers.WordPress/Microsoft.AspNetCore.WebHooks.Receivers.WordPress.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - $(Configurations);CodeAnalysis - ASP.NET Core WordPress WebHooks infrastructure. Contains the WordPressWebHookAttribute class and AddWordPressWebHooks method. - aspnetcore;webhook;receiver;wordpress - - - - - - diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/ApplicationModels/WebHookMetadataProvider.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/ApplicationModels/WebHookMetadataProvider.cs deleted file mode 100644 index 2724dcd..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/ApplicationModels/WebHookMetadataProvider.cs +++ /dev/null @@ -1,411 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using Microsoft.AspNetCore.Mvc.ApplicationModels; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.AspNetCore.WebHooks.Properties; -using Microsoft.Extensions.Logging; - -namespace Microsoft.AspNetCore.WebHooks.ApplicationModels -{ - /// - /// - /// An implementation that adds - /// references to WebHook s. Metadata is stored in - /// and used in and . - /// - /// - /// Detects missing and duplicate services. - /// - /// - public class WebHookMetadataProvider : IApplicationModelProvider - { - private readonly IReadOnlyList _bindingMetadata; - private readonly IReadOnlyList _bodyTypeMetadata; - private readonly IReadOnlyList _eventMetadata; - private readonly IReadOnlyList _pingMetadata; - private readonly ILogger _logger; - - /// - /// Instantiates a new with the given . - /// - /// The collection of services. - /// The . - public WebHookMetadataProvider(IEnumerable metadata, ILoggerFactory loggerFactory) - { - _bindingMetadata = metadata.OfType().ToArray(); - _bodyTypeMetadata = metadata.OfType().ToArray(); - _eventMetadata = metadata.OfType().ToArray(); - _pingMetadata = metadata.OfType().ToArray(); - _logger = loggerFactory.CreateLogger(); - - // Check for duplicate registrations in the collections tracked here. - EnsureUniqueRegistrations(_bindingMetadata); - EnsureUniqueRegistrations(_bodyTypeMetadata); - EnsureUniqueRegistrations(_eventMetadata); - EnsureUniqueRegistrations(_pingMetadata); - - // Check for duplicates in other metadata registrations. - var eventFromBodyMetadata = metadata.OfType().ToArray(); - EnsureUniqueRegistrations(eventFromBodyMetadata); - EnsureUniqueRegistrations(metadata.OfType().ToArray()); - EnsureUniqueRegistrations(metadata.OfType().ToArray()); - - // Check for IWebHookBodyTypeMetadata services that do not also implement IWebHookReceiver. - EnsureValidBodyTypeMetadata(metadata); - - EnsureValidEventFromBodyMetadata(eventFromBodyMetadata, _bodyTypeMetadata); - EnsureValidEventFromBodyMetadata(eventFromBodyMetadata, _eventMetadata); - } - - /// - /// Gets the value used in all - /// instances. - /// - /// - /// Chosen to ensure this provider runs after MVC's . - /// - public static int Order => -500; - - /// - int IApplicationModelProvider.Order => Order; - - /// - public void OnProvidersExecuting(ApplicationModelProviderContext context) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - for (var i = 0; i < context.Result.Controllers.Count; i++) - { - var controller = context.Result.Controllers[i]; - for (var j = 0; j < controller.Actions.Count; j++) - { - var action = controller.Actions[j]; - Apply(action); - } - } - } - - /// - public void OnProvidersExecuted(ApplicationModelProviderContext context) - { - // No-op - } - - private void Apply(ActionModel action) - { - var attribute = action.Attributes.OfType().FirstOrDefault(); - if (attribute == null) - { - // Not a WebHook handler. - return; - } - - var receiverName = attribute.ReceiverName; - if (receiverName != null) - { - var bindingMetadata = _bindingMetadata.FirstOrDefault(metadata => metadata.IsApplicable(receiverName)); - if (bindingMetadata != null) - { - action.Properties[typeof(IWebHookBindingMetadata)] = bindingMetadata; - } - } - - IWebHookEventMetadata eventMetadata; - if (receiverName == null) - { - // Pass along all IWebHookEventMetadata and IWebHookPingRequestMetadata instances. - eventMetadata = null; - action.Properties[typeof(IWebHookEventMetadata)] = _eventMetadata; - action.Properties[typeof(IWebHookPingRequestMetadata)] = _pingMetadata; - } - else - { - eventMetadata = _eventMetadata.FirstOrDefault(metadata => metadata.IsApplicable(receiverName)); - if (eventMetadata != null) - { - action.Properties[typeof(IWebHookEventMetadata)] = eventMetadata; - } - - var pingMetadata = _pingMetadata.FirstOrDefault(metadata => metadata.IsApplicable(receiverName)); - if (pingMetadata != null) - { - action.Properties[typeof(IWebHookPingRequestMetadata)] = pingMetadata; - } - } - - if (attribute is IWebHookEventSelectorMetadata eventSelector && - eventSelector.EventName != null) - { - if (eventMetadata == null && receiverName != null) - { - // IWebHookEventMetadata is mandatory when performing action selection using event names. - _logger.LogCritical( - 0, - "Invalid metadata services found for the '{ReceiverName}' WebHook receiver. Receivers with " + - "attributes implementing '{AttributeMetadataType}' must also provide a " + - "'{ServiceMetadataType}' service. Event selection is impossible otherwise.", - receiverName, - typeof(IWebHookEventSelectorMetadata), - typeof(IWebHookEventMetadata)); - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.MetadataProvider_MissingMetadataServicesForReceiver, - receiverName, - typeof(IWebHookEventSelectorMetadata), - typeof(IWebHookEventMetadata)); - throw new InvalidOperationException(message); - } - - action.Properties[typeof(IWebHookEventSelectorMetadata)] = eventSelector; - } - - // Find the request metadata. IWebHookBodyTypeMetadata is mandatory for every receiver. - if (!(attribute is IWebHookBodyTypeMetadata bodyTypeMetadata)) - { - if (receiverName == null) - { - // Only the GeneralWebHookAttribute should have a null ReceiverName and it implements - // IWebHookBodyTypeMetadata. - var attributeTypeName = attribute.GetType().Name; - _logger.LogCritical( - 1, - "'{AttributeType}' has a null {PropertyName} property but does not implement " + - "'{MetadataType}'.", - attributeTypeName, - nameof(attribute.ReceiverName), - typeof(IWebHookBodyTypeMetadata)); - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.MetadataProvider_MissingAttributeMetadata, - attributeTypeName, - nameof(attribute.ReceiverName), - typeof(IWebHookBodyTypeMetadata)); - throw new InvalidOperationException(message); - } - - bodyTypeMetadata = _bodyTypeMetadata.FirstOrDefault(metadata => metadata.IsApplicable(receiverName)); - if (bodyTypeMetadata == null) - { - _logger.LogCritical( - 2, - "No '{MetadataType}' implementation found for the '{ReceiverName}' WebHook receiver. Each " + - "receiver must register a '{ServiceMetadataType}' or provide a '{AttributeType}' subclass " + - "that implements '{MetadataType}'.", - typeof(IWebHookBodyTypeMetadata), - receiverName, - typeof(IWebHookBodyTypeMetadataService), - typeof(WebHookAttribute), - typeof(IWebHookBodyTypeMetadata)); - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.MetadataProvider_MissingMetadata, - typeof(IWebHookBodyTypeMetadata), - receiverName); - throw new InvalidOperationException(message); - } - } - - action.Properties[typeof(IWebHookBodyTypeMetadata)] = bodyTypeMetadata; - } - - /// - /// Ensure registrations in given are valid. - /// That is, confirm all such metadata also implements . - /// - /// The collection of services. - protected void EnsureValidBodyTypeMetadata(IEnumerable metadata) - { - if (metadata == null) - { - throw new ArgumentNullException(nameof(metadata)); - } - - var nonServiceTypeNames = metadata - .Where(item => item is IWebHookBodyTypeMetadata && !(item is IWebHookBodyTypeMetadataService)) - .Select(item => item.GetType().Name) - .Distinct(); - - var invalidRegistrations = false; - foreach (var typeName in nonServiceTypeNames) - { - invalidRegistrations = true; - _logger.LogCritical( - 3, - "'{ConcreteType}' implements '{MetadataType}' but not '{ServiceType}'.", - typeName, - typeof(IWebHookBodyTypeMetadata), - typeof(IWebHookBodyTypeMetadataService)); - } - - if (invalidRegistrations) - { - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.MetadataProvider_WrongInterface, - typeof(IWebHookBodyTypeMetadata), - typeof(IWebHookBodyTypeMetadataService)); - throw new InvalidOperationException(message); - } - } - - /// - /// Ensure members of given collection are valid. That is, confirm - /// the receivers also provide services. - /// - /// - /// The collection of services. - /// - /// - /// The collection of services. - /// - protected void EnsureValidEventFromBodyMetadata( - IReadOnlyList eventFromBodyMetadata, - IReadOnlyList bodyTypeMetadata) - { - if (eventFromBodyMetadata == null) - { - throw new ArgumentNullException(nameof(eventFromBodyMetadata)); - } - if (bodyTypeMetadata == null) - { - throw new ArgumentNullException(nameof(bodyTypeMetadata)); - } - - var invalidMetadata = false; - var receiversMissingRequiredRequestMetadata = eventFromBodyMetadata - .Where(metadata => !bodyTypeMetadata.Any( - innerMetadata => innerMetadata.IsApplicable(metadata.ReceiverName))) - .Select(metadata => metadata.ReceiverName); - foreach (var receiverName in receiversMissingRequiredRequestMetadata) - { - invalidMetadata = true; - _logger.LogCritical( - 4, - "The '{ReceiverName}' WebHook receiver has invalid '{MetadataType}'. Receivers must also have " + - "'{RequiredMetadataType}'.", - receiverName, - typeof(IWebHookEventFromBodyMetadata), - typeof(IWebHookBodyTypeMetadataService)); - } - - if (invalidMetadata) - { - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.MetadataProvider_MissingMetadataServices, - typeof(IWebHookEventFromBodyMetadata), - typeof(IWebHookBodyTypeMetadataService)); - throw new InvalidOperationException(message); - } - } - - /// - /// Ensure members of given collection are valid. That is, confirm - /// no receiver provides both and - /// services. - /// - /// - /// The collection of services. - /// - /// - /// The collection of services. - /// - protected void EnsureValidEventFromBodyMetadata( - IReadOnlyList eventFromBodyMetadata, - IReadOnlyList eventMetadata) - { - if (eventFromBodyMetadata == null) - { - throw new ArgumentNullException(nameof(eventFromBodyMetadata)); - } - if (eventMetadata == null) - { - throw new ArgumentNullException(nameof(eventMetadata)); - } - - var invalidMetadata = false; - var receiversWithConflictingMetadata = eventFromBodyMetadata - .Where(metadata => eventMetadata.Any( - innerMetadata => innerMetadata.IsApplicable(metadata.ReceiverName))) - .Select(metadata => metadata.ReceiverName); - foreach (var receiverName in receiversWithConflictingMetadata) - { - invalidMetadata = true; - _logger.LogCritical( - 4, - "Invalid metadata services found for the '{ReceiverName}' WebHook receiver. Receivers must not " + - "provide both '{EventFromBodyMetadataType}' and '{EventMetadataType}' services.", - receiverName, - typeof(IWebHookEventFromBodyMetadata), - typeof(IWebHookEventMetadata)); - } - - if (invalidMetadata) - { - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.MetadataProvider_ConflictingMetadataServices, - typeof(IWebHookEventFromBodyMetadata), - typeof(IWebHookEventMetadata)); - throw new InvalidOperationException(message); - } - } - - /// - /// Ensure given collection does not contain duplicate registrations. That is, - /// confirm the registration for each - /// is unique. - /// - /// - /// The interface of the to check. - /// - /// The collection of services to check. - /// - /// Thrown if duplicates exist in . - /// - protected void EnsureUniqueRegistrations(IReadOnlyList services) - where TService : IWebHookReceiver - { - if (services == null) - { - throw new ArgumentNullException(nameof(services)); - } - - var duplicateReceiverNames = services - .GroupBy(item => item.ReceiverName, StringComparer.OrdinalIgnoreCase) - .Where(group => group.Count() != 1) - .Select(group => group.Key); - - var hasDuplicates = false; - foreach (var receiverName in duplicateReceiverNames) - { - hasDuplicates = true; - _logger.LogCritical( - 5, - "Duplicate '{MetadataType}' registrations found for the '{ReceiverName}' WebHook receiver.", - typeof(TService), - receiverName); - } - - if (hasDuplicates) - { - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.MetadataProvider_DuplicateMetadata, - typeof(TService)); - throw new InvalidOperationException(message); - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/ApplicationModels/WebHookModelBindingProvider.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/ApplicationModels/WebHookModelBindingProvider.cs deleted file mode 100644 index 3ed3ac4..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/ApplicationModels/WebHookModelBindingProvider.cs +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Xml.Linq; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc.ApplicationModels; -using Microsoft.AspNetCore.Mvc.ModelBinding; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.AspNetCore.WebHooks.Properties; -using Newtonsoft.Json.Linq; - -namespace Microsoft.AspNetCore.WebHooks.ApplicationModels -{ - /// - /// An implementation that adds and - /// information to s of WebHook actions. - /// - public class WebHookModelBindingProvider : IApplicationModelProvider - { - /// - public int Order => WebHookMetadataProvider.Order + 20; - - /// - public void OnProvidersExecuting(ApplicationModelProviderContext context) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - for (var i = 0; i < context.Result.Controllers.Count; i++) - { - var controller = context.Result.Controllers[i]; - for (var j = 0; j < controller.Actions.Count; j++) - { - var action = controller.Actions[j]; - var attribute = action.Attributes.OfType().FirstOrDefault(); - if (attribute == null) - { - // Not a WebHook handler. - continue; - } - - action.Properties.TryGetValue(typeof(IWebHookBindingMetadata), out var bindingMetadata); - action.Properties.TryGetValue(typeof(IWebHookBodyTypeMetadata), out var bodyTypeMetadata); - for (var k = 0; k < action.Parameters.Count; k++) - { - var parameter = action.Parameters[k]; - Apply( - (IWebHookBindingMetadata)bindingMetadata, - (IWebHookBodyTypeMetadata)bodyTypeMetadata, - parameter); - } - } - } - } - - /// - public void OnProvidersExecuted(ApplicationModelProviderContext context) - { - // No-op - } - - private void Apply( - IWebHookBindingMetadata bindingMetadata, - IWebHookBodyTypeMetadata bodyTypeMetadata, - ParameterModel parameter) - { - var bindingInfo = parameter.BindingInfo; - if (bindingInfo?.BinderModelName != null || - bindingInfo?.BinderType != null || - bindingInfo?.BindingSource != null) - { - // User was explicit. Nothing to do. - return; - } - - if (bindingInfo == null) - { - bindingInfo = parameter.BindingInfo = new BindingInfo(); - } - - var parameterName = parameter.ParameterName; - var parameterType = parameter.ParameterInfo.ParameterType; - switch (parameterName.ToUpperInvariant()) - { - case "ACTION": - case "ACTIONS": - case "ACTIONNAME": - case "ACTIONNAMES": - SourceEvent(bindingInfo, parameterType); - break; - - case "DATA": - SourceData(bindingInfo, bodyTypeMetadata); - break; - - case "EVENT": - case "EVENTS": - case "EVENTNAME": - case "EVENTNAMES": - SourceEvent(bindingInfo, parameterType); - break; - - case "ID": - SourceId(bindingInfo, parameterType); - break; - - case "RECEIVER": - case "RECEIVERNAME": - SourceReceiver(bindingInfo, parameterType); - break; - - case "RECEIVERID": - SourceId(bindingInfo, parameterType); - break; - - case "WEBHOOKRECEIVER": - SourceReceiver(bindingInfo, parameterType); - break; - - default: - // If additional parameters are configured and match, map them. If not, treat IFormCollection, - // JContainer and XElement parameters as data. IsAssignableFrom(...) looks reversed because this - // check is about model binding system support, not an actual assignment to the parameter. - if (!TrySourceAdditionalParameter(bindingInfo, bindingMetadata, parameterName) && - (typeof(IFormCollection).IsAssignableFrom(parameterType) || - typeof(JToken).IsAssignableFrom(parameterType) || - typeof(XElement).IsAssignableFrom(parameterType))) - { - SourceData(bindingInfo, bodyTypeMetadata); - } - break; - } - } - - private void SourceData(BindingInfo bindingInfo, IWebHookBodyTypeMetadata bodyTypeMetadata) - { - if (bodyTypeMetadata == null) - { - return; - } - - if (bodyTypeMetadata.BodyType == WebHookBodyType.Form) - { - bindingInfo.BinderModelName = WebHookConstants.ModelStateBodyModelName; - bindingInfo.BindingSource = BindingSource.Form; - return; - } - - bindingInfo.BinderModelName = WebHookConstants.ModelStateBodyModelName; - bindingInfo.BindingSource = BindingSource.Body; - } - - private static void SourceEvent(BindingInfo bindingInfo, Type parameterType) - { - // IsAssignableFrom(...) looks reversed because this check is about model binding system support, not an - // actual assignment to the parameter. - if (typeof(string) != parameterType && - !typeof(IEnumerable).IsAssignableFrom(parameterType)) - { - // Unexpected / unsupported type. Do nothing. - return; - } - - bindingInfo.BinderModelName = WebHookConstants.EventKeyName; - bindingInfo.BindingSource = BindingSource.Path; - } - - private static void SourceId(BindingInfo bindingInfo, Type parameterType) - { - if (typeof(string) != parameterType) - { - // Unexpected / unsupported type. Do nothing. - return; - } - - bindingInfo.BinderModelName = WebHookConstants.IdKeyName; - bindingInfo.BindingSource = BindingSource.Path; - } - - private static void SourceReceiver(BindingInfo bindingInfo, Type parameterType) - { - if (typeof(string) != parameterType) - { - // Unexpected / unsupported type. Do nothing. - return; - } - - bindingInfo.BinderModelName = WebHookConstants.ReceiverKeyName; - bindingInfo.BindingSource = BindingSource.Path; - } - - private static bool TrySourceAdditionalParameter( - BindingInfo bindingInfo, - IWebHookBindingMetadata bindingMetadata, - string parameterName) - { - var parameter = bindingMetadata?.Parameters - .FirstOrDefault(item => string.Equals(parameterName, item.Name, StringComparison.OrdinalIgnoreCase)); - if (parameter == null) - { - return false; - } - - bindingInfo.BinderModelName = parameter.SourceName; - switch (parameter.ParameterType) - { - case WebHookParameterType.Header: - bindingInfo.BindingSource = BindingSource.Header; - break; - - case WebHookParameterType.RouteValue: - bindingInfo.BindingSource = BindingSource.Path; - break; - - case WebHookParameterType.QueryParameter: - bindingInfo.BindingSource = BindingSource.Query; - break; - - default: - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.General_InvalidEnumValue, - nameof(WebHookParameterType), - parameter.ParameterType); - throw new InvalidOperationException(message); - } - - return true; - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/ApplicationModels/WebHookRoutingProvider.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/ApplicationModels/WebHookRoutingProvider.cs deleted file mode 100644 index 2e67a6b..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/ApplicationModels/WebHookRoutingProvider.cs +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.Linq; -using Microsoft.AspNetCore.Mvc.ActionConstraints; -using Microsoft.AspNetCore.Mvc.ApplicationModels; -using Microsoft.AspNetCore.WebHooks.Filters; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.AspNetCore.WebHooks.Properties; -using Microsoft.AspNetCore.WebHooks.Routing; -using Microsoft.Extensions.Logging; - -namespace Microsoft.AspNetCore.WebHooks.ApplicationModels -{ - /// - /// An implementation that adds attribute routing information to WebHook - /// actions. - /// - public class WebHookRoutingProvider : IApplicationModelProvider - { - private readonly WebHookReceiverExistsConstraint _existsConstraint; - private readonly WebHookEventMapperConstraint _eventMapperConstraint; - private readonly ILoggerFactory _loggerFactory; - - /// - /// Instantiates a new with the given - /// , and - /// . - /// - /// The . - /// The . - /// The . - public WebHookRoutingProvider( - WebHookReceiverExistsConstraint existsConstraint, - WebHookEventMapperConstraint eventMapperConstraint, - ILoggerFactory loggerFactory) - { - _existsConstraint = existsConstraint; - _eventMapperConstraint = eventMapperConstraint; - _loggerFactory = loggerFactory; - } - - /// - public int Order => WebHookMetadataProvider.Order + 10; - - /// - public void OnProvidersExecuting(ApplicationModelProviderContext context) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - for (var i = 0; i < context.Result.Controllers.Count; i++) - { - var controller = context.Result.Controllers[i]; - for (var j = 0; j < controller.Actions.Count; j++) - { - var action = controller.Actions[j]; - Apply(action); - } - } - } - - /// - public void OnProvidersExecuted(ApplicationModelProviderContext context) - { - // No-op - } - - /// - public void Apply(ActionModel action) - { - var attribute = action.Attributes.OfType().FirstOrDefault(); - if (attribute == null) - { - // Not a WebHook handler. - return; - } - - var template = ChooseTemplate(action.RouteValues); - var selectors = action.Selectors; - if (selectors.Count == 0) - { - var selector = new SelectorModel(); - selectors.Add(selector); - - AddTemplate(attribute, template, selector); - } - else - { - for (var i = 0; i < selectors.Count; i++) - { - var selector = selectors[i]; - AddTemplate(attribute, template, selector); - } - } - - AddConstraints(attribute, selectors); - AddConstraints(action.Properties, selectors); - - if (action.Properties.TryGetValue(typeof(IWebHookBodyTypeMetadata), out var bodyTypeMetadata)) - { - action.Filters.Add(new WebHookVerifyBodyTypeFilter( - (IWebHookBodyTypeMetadata)bodyTypeMetadata, - _loggerFactory)); - } - } - - // Use a constant template since we'll need constraints in any case. That is, need constraints either to match - // receiver names and ids (current choice) or need them to map another route value to what model binding expects. - private static string ChooseTemplate(IDictionary routeValues) - { - var template = "/api/webhooks/incoming/" - + $"{{{WebHookConstants.ReceiverKeyName}}}/" - + $"{{{WebHookConstants.IdKeyName}?}}"; - - return template; - } - - // Set the template for given SelectorModel. Similar to WebHookActionAttributeBase implementing - // IRouteTemplateProvider. - private static void AddTemplate(WebHookAttribute attribute, string template, SelectorModel selector) - { - if (selector.AttributeRouteModel?.Template != null) - { - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.RoutingProvider_MixedRouteWithWebHookAttribute, - attribute.GetType().Name, - selector.AttributeRouteModel.Attribute?.GetType().Name); - throw new InvalidOperationException(message); - } - - if (selector.AttributeRouteModel == null) - { - selector.AttributeRouteModel = new AttributeRouteModel(); - } - - selector.AttributeRouteModel.Template = template; - } - - private static void AddConstraint(IActionConstraintMetadata constraint, IList selectors) - { - for (var i = 0; i < selectors.Count; i++) - { - var selector = selectors[i]; - selector.ActionConstraints.Add(constraint); - } - } - - private void AddConstraints(WebHookAttribute attribute, IList selectors) - { - AddConstraint(_existsConstraint, selectors); - - if (attribute.ReceiverName != null) - { - var constraint = new WebHookReceiverNameConstraint(attribute.ReceiverName); - AddConstraint(constraint, selectors); - } - - if (attribute.Id != null) - { - var constraint = new WebHookIdConstraint(attribute.Id); - AddConstraint(constraint, selectors); - } - } - - private void AddConstraints(IDictionary properties, IList selectors) - { - if (properties.TryGetValue(typeof(IWebHookEventMetadata), out var eventMetadata)) - { - AddConstraint(_eventMapperConstraint, selectors); - } - - if (properties.TryGetValue(typeof(IWebHookEventSelectorMetadata), out var eventSourceMetadata)) - { - var eventName = ((IWebHookEventSelectorMetadata)eventSourceMetadata).EventName; - if (eventName != null) - { - // IWebHookEventMetadata is mandatory when performing action selection using event names. - Debug.Assert(eventMetadata != null); - properties.TryGetValue(typeof(IWebHookPingRequestMetadata), out var pingMetadata); - - // Use eventMetadata to choose constraint type because IWebHookPingRequestMetadata is optional. - IActionConstraintMetadata constraint; - if (eventMetadata is IWebHookEventMetadata) - { - constraint = new WebHookSingleEventNamesConstraint( - eventName, - ((IWebHookPingRequestMetadata)pingMetadata)?.PingEventName); - } - else - { - constraint = new WebHookMultipleEventNamesConstraint( - eventName, - (IReadOnlyList)pingMetadata); - } - - AddConstraint(constraint, selectors); - } - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Extensions/WebHookMvcBuilderExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Extensions/WebHookMvcBuilderExtensions.cs deleted file mode 100644 index 9fbdb1c..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Extensions/WebHookMvcBuilderExtensions.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using Microsoft.AspNetCore.WebHooks.Internal; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up WebHooks in an . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class WebHookMvcBuilderExtensions - { - /// - /// - /// Add WebHook configuration and services to the specified . - /// - /// - /// 'WebHooks:{receiver name}:SecretKey:default' configuration values usually contain secret keys for - /// WebHook URIs of the form 'https://{host}/api/webhooks/incoming/{receiver name}' (with a - /// ?code=... query string for some receivers). 'WebHooks:{receiver name}:SecretKey:{id}' - /// configuration values usually contain secret keys for WebHook URIs of the form - /// 'https://{host}/api/webhooks/incoming/{receiver name}/{id}'. - /// - /// - /// The to configure. - /// The . - public static IMvcBuilder AddWebHooks(this IMvcBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - WebHookServiceCollectionSetup.AddWebHookServices(builder.Services); - - return builder; - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Extensions/WebHookMvcCoreBuilderExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Extensions/WebHookMvcCoreBuilderExtensions.cs deleted file mode 100644 index c09e9b6..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Extensions/WebHookMvcCoreBuilderExtensions.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using Microsoft.AspNetCore.WebHooks.Internal; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up WebHooks in an . - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class WebHookMvcCoreBuilderExtensions - { - /// - /// - /// Add WebHook configuration and services to the specified . - /// - /// - /// 'WebHooks:{receiver name}:SecretKey:default' configuration values usually contain secret keys for - /// WebHook URIs of the form 'https://{host}/api/webhooks/incoming/{receiver name}' (with a - /// ?code=... query string for some receivers). 'WebHooks:{receiver name}:SecretKey:{id}' - /// configuration values usually contain secret keys for WebHook URIs of the form - /// 'https://{host}/api/webhooks/incoming/{receiver name}/{id}'. - /// - /// - /// The to configure. - /// The . - public static IMvcCoreBuilder AddWebHooks(this IMvcCoreBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - WebHookServiceCollectionSetup.AddWebHookServices(builder.Services); - - return builder; - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Extensions/WebHookRouteDataExtensions.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Extensions/WebHookRouteDataExtensions.cs deleted file mode 100644 index ce26a1c..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Extensions/WebHookRouteDataExtensions.cs +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel; -using System.Linq; -using Microsoft.AspNetCore.WebHooks; -using Microsoft.AspNetCore.WebHooks.Routing; -using Microsoft.Extensions.Primitives; - -namespace Microsoft.AspNetCore.Routing -{ - /// - /// Extension methods for the class. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class WebHookRouteDataExtensions - { - private static readonly string[] EventKeyNames = Enumerable.Range(0, 100) - .Select(i => $"{WebHookConstants.EventKeyName}[{i}]") - .ToArray(); - - /// - /// Gets an indication a WebHook receiver for the current request is configured. - /// - /// The for the current request. - /// - /// if an indication ran successfully was - /// found in the ; otherwise. - /// - public static bool GetWebHookReceiverExists(this RouteData routeData) - { - if (routeData == null) - { - throw new ArgumentNullException(nameof(routeData)); - } - - if (routeData.Values.TryGetValue(WebHookConstants.ReceiverExistsKeyName, out var exists)) - { - var receiverExists = (bool)exists; - return receiverExists == true; - } - - return false; - } - - /// - /// Gets the single WebHook event name for the current request. - /// - /// The for the current request. - /// Set to the event name identified in the request. - /// - /// if exactly one event name was found in the ; - /// otherwise. - /// - public static bool TryGetWebHookEventName(this RouteData routeData, out string eventName) - { - if (routeData == null) - { - throw new ArgumentNullException(nameof(routeData)); - } - - if (routeData.Values.TryGetValue(WebHookConstants.EventKeyName, out var name)) - { - var potentialEventName = (string)name; - if (!string.IsNullOrEmpty(potentialEventName)) - { - eventName = potentialEventName; - return true; - } - } - - eventName = null; - return false; - } - - /// - /// Gets the WebHook event names for the current request. - /// - /// The for the current request. - /// Set to the event names identified in the request. - /// - /// if event names were found in the ; - /// otherwise. - /// - public static bool TryGetWebHookEventNames(this RouteData routeData, out string[] eventNames) - { - if (routeData == null) - { - throw new ArgumentNullException(nameof(routeData)); - } - - if (routeData.Values.TryGetValue(WebHookConstants.EventKeyName, out var name)) - { - var eventName = (string)name; - if (!string.IsNullOrEmpty(eventName)) - { - eventNames = new[] { eventName }; - return true; - } - } - - var count = 0; - while (count < EventKeyNames.Length && - routeData.Values.ContainsKey(EventKeyNames[count])) - { - count++; - } - - if (count != 0) - { - eventNames = new string[count]; - for (var i = 0; i < count; i++) - { - eventNames[i] = (string)routeData.Values[EventKeyNames[i]]; - } - - return true; - } - - eventNames = null; - return false; - } - - /// - /// Gets the WebHook receiver id for the current request. - /// - /// The for the current request. - /// Set to the id of the requested receiver. - /// - /// if a receiver id was found in the ; - /// otherwise. - /// - public static bool TryGetWebHookReceiverId(this RouteData routeData, out string id) - { - if (routeData == null) - { - throw new ArgumentNullException(nameof(routeData)); - } - - if (routeData.Values.TryGetValue(WebHookConstants.IdKeyName, out var identifier)) - { - id = (string)identifier; - return !string.IsNullOrEmpty(id); - } - - id = null; - return false; - } - - /// - /// Gets the WebHook receiver name for the current request. - /// - /// The for the current request. - /// Set to the name of the requested receiver. - /// - /// if a receiver name was found in the ; - /// otherwise. - /// - public static bool TryGetWebHookReceiverName(this RouteData routeData, out string receiverName) - { - if (routeData == null) - { - throw new ArgumentNullException(nameof(routeData)); - } - - if (routeData.Values.TryGetValue(WebHookConstants.ReceiverKeyName, out var receiver)) - { - receiverName = (string)receiver; - return !string.IsNullOrEmpty(receiverName); - } - - receiverName = null; - return false; - } - - /// - /// Stores the for the current request in . - /// - /// The for the current request. - /// The event names found in the request. - public static void SetWebHookEventNames(this RouteData routeData, StringValues eventNames) - { - if (routeData == null) - { - throw new ArgumentNullException(nameof(routeData)); - } - - if (eventNames.Count == 1) - { - routeData.Values[WebHookConstants.EventKeyName] = eventNames[0]; - } - else if (eventNames.Count > 1) - { - for (var i = 0; i < eventNames.Count && i < EventKeyNames.Length; i++) - { - routeData.Values[EventKeyNames[i]] = eventNames[i]; - } - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookEventMapperFilter.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookEventMapperFilter.cs deleted file mode 100644 index cecf7b5..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookEventMapperFilter.cs +++ /dev/null @@ -1,221 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Threading.Tasks; -using System.Xml.Linq; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.AspNetCore.WebHooks.Properties; -using Microsoft.AspNetCore.WebHooks.Utilities; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Primitives; -using Newtonsoft.Json.Linq; - -namespace Microsoft.AspNetCore.WebHooks.Filters -{ - /// - /// - /// An implementation which uses to - /// determine the event names for a WebHook request. Reads the event names from the request body and makes them - /// available for model binding and short-circuiting ping requests but not for action selection. - /// - /// - /// This filter accepts all requests for receivers lacking or with - /// set to . Otherwise, the filter - /// short-circuits requests with no event names in the body. - /// - /// - /// - /// This filter ignores errors other filters will handle but rejects requests that cause model binding failures. - /// - public class WebHookEventMapperFilter : IAsyncResourceFilter - { - private readonly IReadOnlyList _bodyTypeMetadata; - private readonly IReadOnlyList _eventMetadata; - private readonly ILogger _logger; - private readonly IWebHookRequestReader _requestReader; - - /// - /// Instantiates a new instance with the given - /// , and . - /// - /// The . - /// The collection of services. - /// The . - public WebHookEventMapperFilter( - ILoggerFactory loggerFactory, - IEnumerable metadata, - IWebHookRequestReader requestReader) - { - _eventMetadata = metadata.OfType().ToArray(); - - // No need to track metadata unless it's applicable in this filter. - _bodyTypeMetadata = metadata - .OfType() - .Where(bodyTypeMetadata => _eventMetadata.Any( - eventMetadata => eventMetadata.IsApplicable(bodyTypeMetadata.ReceiverName))) - .ToArray(); - - _logger = loggerFactory.CreateLogger(); - _requestReader = requestReader; - } - - /// - /// Gets the recommended for all - /// instances. The recommended filter sequence is - /// - /// - /// Confirm signature or code query parameter (e.g. in or a - /// subclass). - /// - /// - /// Confirm required headers, entries and query parameters are provided (in - /// ). - /// - /// - /// Short-circuit GET or HEAD requests, if receiver supports either (in - /// ). - /// - /// Confirm it's a POST request (in ). - /// Confirm body type (in ). - /// - /// Map event name(s), if not done in for this receiver (in - /// this filter). - /// - /// - /// Short-circuit ping requests, if not done in for this receiver (in - /// ). - /// - /// - /// - public static int Order => WebHookVerifyBodyTypeFilter.Order + 10; - - /// - public virtual async Task OnResourceExecutionAsync( - ResourceExecutingContext context, - ResourceExecutionDelegate next) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - if (next == null) - { - throw new ArgumentNullException(nameof(next)); - } - - var routeData = context.RouteData; - if (!routeData.TryGetWebHookReceiverName(out var receiverName)) - { - await next(); - return; - } - - var eventMetadata = _eventMetadata.FirstOrDefault(metadata => metadata.IsApplicable(receiverName)); - if (eventMetadata == null) - { - await next(); - return; - } - - StringValues eventNames; - var bodyTypeMetadata = _bodyTypeMetadata.First(metadata => metadata.IsApplicable(receiverName)); - switch (bodyTypeMetadata.BodyType) - { - case WebHookBodyType.Form: - var form = await _requestReader.ReadAsFormDataAsync(context); - if (form == null) - { - // ReadAsFormDataAsync returns null only when other filters will log and return errors - // about the same conditions. Let those filters run. - await next(); - return; - } - - eventNames = form[eventMetadata.BodyPropertyPath]; - break; - - case WebHookBodyType.Json: - var json = await _requestReader.ReadBodyAsync(context); - if (json == null) - { - var modelState = context.ModelState; - if (modelState.IsValid) - { - // ReadAsJContainerAsync returns null when model state is valid only when other filters - // will log and return errors about the same conditions. Let those filters run. - await next(); - } - else - { - context.Result = new BadRequestObjectResult(modelState); - } - - return; - } - - eventNames = ObjectPathUtilities.GetStringValues(json, eventMetadata.BodyPropertyPath); - break; - - case WebHookBodyType.Xml: - var xml = await _requestReader.ReadBodyAsync(context); - if (xml == null) - { - var modelState = context.ModelState; - if (modelState.IsValid) - { - // ReadAsXmlAsync returns null when model state is valid only when other filters will log - // and return errors about the same conditions. Let those filters run. - await next(); - } - else - { - context.Result = new BadRequestObjectResult(modelState); - } - - return; - } - - eventNames = ObjectPathUtilities.GetStringValues(xml, eventMetadata.BodyPropertyPath); - break; - - default: - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.General_InvalidEnumValue, - nameof(WebHookBodyType), - bodyTypeMetadata.BodyType); - throw new InvalidOperationException(message); - } - - if (StringValues.IsNullOrEmpty(eventNames) && !eventMetadata.AllowMissing) - { - _logger.LogError( - 500, - "A '{ReceiverName}' WebHook request must contain a match for '{BodyPropertyPath}' in the HTTP " + - "request entity body indicating the type or types of event.", - receiverName, - eventMetadata.BodyPropertyPath); - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.EventMapper_NoBodyProperty, - receiverName, - eventMetadata.BodyPropertyPath); - context.Result = new BadRequestObjectResult(message); - - return; - } - - routeData.SetWebHookEventNames(eventNames); - - await next(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookGetRequestFilter.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookGetRequestFilter.cs deleted file mode 100644 index 781592d..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookGetRequestFilter.cs +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.AspNetCore.WebHooks.Properties; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Primitives; - -namespace Microsoft.AspNetCore.WebHooks.Filters -{ - /// - /// An to verify secret keys and short-circuit WebHook GET requests. - /// - public class WebHookGetRequestFilter : WebHookSecurityFilter, IResourceFilter - { - private readonly IReadOnlyList _getRequestMetadata; - - /// - /// Instantiates a new instance. - /// - /// - /// The used to initialize . - /// - /// - /// The used to initialize - /// . - /// - /// - /// The used to initialize . - /// - /// The collection of services. - public WebHookGetRequestFilter( - IConfiguration configuration, - IHostingEnvironment hostingEnvironment, - ILoggerFactory loggerFactory, - IEnumerable metadata) - : base(configuration, hostingEnvironment, loggerFactory) - { - _getRequestMetadata = metadata.OfType().ToArray(); - } - - /// - /// Gets the recommended for all - /// instances. The recommended filter sequence is - /// - /// - /// Confirm signature or code query parameter e.g. in or other - /// subclass. - /// - /// - /// Confirm required headers, entries and query parameters are provided (in - /// ). - /// - /// Short-circuit GET or HEAD requests, if receiver supports either (in this filter). - /// Confirm it's a POST request (in ). - /// Confirm body type (in ). - /// - /// Short-circuit ping requests, if not done in this filter for this receiver (in - /// ). - /// - /// - /// - public new static int Order => WebHookVerifyRequiredValueFilter.Order + 10; - - /// - public void OnResourceExecuting(ResourceExecutingContext context) - { - if (context == null) - { - throw new System.ArgumentNullException(nameof(context)); - } - - var routeData = context.RouteData; - if (routeData.TryGetWebHookReceiverName(out var receiverName) && - HttpMethods.IsGet(context.HttpContext.Request.Method)) - { - var getRequestMetadata = _getRequestMetadata - .FirstOrDefault(metadata => metadata.IsApplicable(receiverName)); - if (getRequestMetadata != null) - { - // First verify that we have the secret key configuration value. This may be redundant if the - // receiver also implements IWebHookVerifyCodeMetadata in its metadata. However this verification - // is necessary for some receivers because signature verification (for example) is not possible - // without a body. - var secretKey = GetSecretKey( - receiverName, - routeData, - getRequestMetadata.SecretKeyMinLength, - getRequestMetadata.SecretKeyMaxLength); - if (secretKey == null) - { - context.Result = new NotFoundResult(); - return; - } - - if (getRequestMetadata.ChallengeQueryParameterName == null) - { - // Simple case. Have done all necessary verification. - context.Result = new OkResult(); - return; - } - - var request = context.HttpContext.Request; - context.Result = GetChallengeResponse(getRequestMetadata, receiverName, request, routeData); - } - } - } - - /// - public void OnResourceExecuted(ResourceExecutedContext context) - { - // No-op - } - - private IActionResult GetChallengeResponse( - IWebHookGetRequestMetadata getRequestMetadata, - string receiverName, - HttpRequest request, - RouteData routeData) - { - // Get the 'challenge' parameter from the request URI. - var challenge = request.Query[getRequestMetadata.ChallengeQueryParameterName]; - if (StringValues.IsNullOrEmpty(challenge)) - { - Logger.LogError( - 400, - "A '{ReceiverName}' WebHook verification request must contain a '{ParameterName}' query " + - "parameter.", - receiverName, - getRequestMetadata.ChallengeQueryParameterName); - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.GetRequest_NoQueryParameter, - receiverName, - getRequestMetadata.ChallengeQueryParameterName); - var noChallenge = new BadRequestObjectResult(message); - - return noChallenge; - } - - // Echo the challenge back to the caller. - return new ContentResult - { - Content = challenge, - }; - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookPingRequestFilter.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookPingRequestFilter.cs deleted file mode 100644 index 7490e40..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookPingRequestFilter.cs +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.Extensions.Logging; - -namespace Microsoft.AspNetCore.WebHooks.Filters -{ - /// - /// An to short-circuit ping WebHook requests. - /// - public class WebHookPingRequestFilter : IResourceFilter - { - private readonly ILogger _logger; - private readonly IReadOnlyList _pingMetadata; - - /// - /// Instantiates a new instance. - /// - /// The . - /// The collection of services. - public WebHookPingRequestFilter(ILoggerFactory loggerFactory, IEnumerable metadata) - { - _logger = loggerFactory.CreateLogger(); - _pingMetadata = metadata.OfType().ToArray(); - } - - /// - /// Gets the recommended for all - /// instances. The recommended filter sequence is - /// - /// - /// Confirm signature or code query parameter e.g. in or other - /// subclass. - /// - /// - /// Confirm required headers, entries and query parameters are provided (in - /// ). - /// - /// - /// Short-circuit GET or HEAD requests, if receiver supports either (in ). - /// - /// Confirm it's a POST request (in ). - /// Confirm body type (in ). - /// - /// Short-circuit ping requests, if not done in for this receiver (in - /// this filter). - /// - /// - /// - public static int Order => WebHookVerifyBodyTypeFilter.Order + 10; - - /// - public void OnResourceExecuting(ResourceExecutingContext context) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var routeData = context.RouteData; - if (routeData.TryGetWebHookReceiverName(out var receiverName)) - { - var pingMetadata = _pingMetadata.FirstOrDefault(metadata => metadata.IsApplicable(receiverName)); - if (pingMetadata != null && - routeData.TryGetWebHookEventName(out var eventName)) - { - // If this is a ping request, short-circuit further processing. - if (string.Equals(eventName, pingMetadata.PingEventName, StringComparison.OrdinalIgnoreCase)) - { - _logger.LogInformation( - 0, - "Received a Ping Event for the '{ReceiverName}' WebHook receiver -- ignoring.", - receiverName); - - context.Result = new OkResult(); - return; - } - } - } - } - - /// - public void OnResourceExecuted(ResourceExecutedContext context) - { - // No-op - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookReceiverExistsFilter.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookReceiverExistsFilter.cs deleted file mode 100644 index 035fb5b..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookReceiverExistsFilter.cs +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; - -namespace Microsoft.AspNetCore.WebHooks.Filters -{ - /// - /// An that confirms the is - /// configured and ran successfully for this request. Also confirms either - /// is applicable or at least one filter is configured to handle this request. - /// The minimal configuration for a receiver without includes a - /// subclass to verify signatures or otherwise check secret keys. - /// - public class WebHookReceiverExistsFilter : IResourceFilter - { - private readonly IReadOnlyList _codeVerifierMetadata; - private readonly ILogger _logger; - - /// - /// Instantiates a new with the given - /// . - /// - /// The collection of services. - /// The . - public WebHookReceiverExistsFilter(IEnumerable metadata, ILoggerFactory loggerFactory) - { - _codeVerifierMetadata = metadata.OfType().ToArray(); - _logger = loggerFactory.CreateLogger(); - } - - /// - /// - /// Confirms the is configured and ran successfully for - /// this request. Also confirms at least one filter is configured to handle this - /// request. - /// - /// - /// Logs an informational message when both confirmations succeed. If either confirmation fails, sets - /// to a with - /// set to . - /// - /// - /// The . - public void OnResourceExecuting(ResourceExecutingContext context) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (context.RouteData.TryGetWebHookReceiverName(out var receiverName)) - { - if (!context.RouteData.GetWebHookReceiverExists()) - { - _logger.LogCritical( - 0, - "Unable to find WebHook routing constraints for the '{ReceiverName}' receiver. Please add " + - "the required configuration by calling a receiver-specific method that calls " + - "'{BuilderInterface}.{BuilderMethod}' or '{CoreInterface}.{CoreBuilderMethod}' in the " + - "application startup code. For example, call " + - "'{GitHubBuilderInterface}.{GitHubBuilderMethod}' to configure a minimal GitHub receiver.", - receiverName, - nameof(IMvcBuilder), - nameof(WebHookMvcBuilderExtensions.AddWebHooks), - nameof(IMvcCoreBuilder), - nameof(WebHookMvcCoreBuilderExtensions.AddWebHooks), - nameof(IMvcCoreBuilder), - "AddGitHubWebHooks"); - - context.Result = new StatusCodeResult(StatusCodes.Status500InternalServerError); - return; - } - - // Check for receiver-specific filters only for receivers that do _not_ use code verification. - if (!_codeVerifierMetadata.Any(metadata => metadata.IsApplicable(receiverName))) - { - var found = false; - for (var i = 0; i < context.Filters.Count; i++) - { - var filter = context.Filters[i]; - if (filter is IWebHookReceiver receiver && receiver.IsApplicable(receiverName)) - { - found = true; - break; - } - } - - if (!found) - { - // This case is actually more likely a gap in the receiver-specific configuration method. - _logger.LogCritical( - 1, - "Unable to find WebHook filters for the '{ReceiverName}' receiver. Please add the " + - "required configuration by calling a receiver-specific method that calls " + - "'{BuilderInterface}.{BuilderMethod}' or '{CoreInterface}.{CoreBuilderMethod}' in the " + - "application startup code. For example, call " + - "'{GitHubBuilderInterface}.{GitHubBuilderMethod}' to configure a minimal GitHub receiver.", - receiverName, - nameof(IMvcBuilder), - nameof(WebHookMvcBuilderExtensions.AddWebHooks), - nameof(IMvcCoreBuilder), - nameof(WebHookMvcCoreBuilderExtensions.AddWebHooks), - nameof(IMvcCoreBuilder), - "AddGitHubWebHooks"); - - context.Result = new StatusCodeResult(StatusCodes.Status500InternalServerError); - return; - } - } - } - else - { - // Routing not configured at all (no template) but the request reached this action. - _logger.LogCritical( - 2, - "Unable to find WebHook routing information in the request. Please add the required " + - "configuration by calling a receiver-specific method that calls " + - "'{BuilderInterface}.{BuilderMethod}' or '{CoreInterface}.{CoreBuilderMethod}' in the " + - "application startup code. For example, call '{GitHubBuilderInterface}.{GitHubBuilderMethod}' " + - "to configure a minimal GitHub receiver.", - nameof(IMvcBuilder), - nameof(WebHookMvcBuilderExtensions.AddWebHooks), - nameof(IMvcCoreBuilder), - nameof(WebHookMvcCoreBuilderExtensions.AddWebHooks), - nameof(IMvcCoreBuilder), - "AddGitHubWebHooks"); - - context.Result = new StatusCodeResult(StatusCodes.Status500InternalServerError); - return; - } - - context.RouteData.TryGetWebHookReceiverId(out var id); - _logger.LogInformation( - 3, - "Processing incoming WebHook request with receiver '{ReceiverName}' and id '{Id}'.", - receiverName, - id); - } - - /// - public void OnResourceExecuted(ResourceExecutedContext context) - { - // No-op - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookSecurityFilter.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookSecurityFilter.cs deleted file mode 100644 index 9915bf4..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookSecurityFilter.cs +++ /dev/null @@ -1,354 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Globalization; -using System.Runtime.CompilerServices; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.WebHooks.Properties; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; - -namespace Microsoft.AspNetCore.WebHooks.Filters -{ - /// - /// Base class for or - /// implementations that for example verify request signatures or code query parameters. Subclasses may - /// also implement . Subclasses should have an - /// equal to . - /// - public abstract class WebHookSecurityFilter - { - /// - /// Instantiates a new instance. - /// - /// - /// The used to initialize . - /// - /// - /// The used to initialize . - /// - /// - /// The used to initialize . - /// - protected WebHookSecurityFilter( - IConfiguration configuration, - IHostingEnvironment hostingEnvironment, - ILoggerFactory loggerFactory) - { - if (configuration == null) - { - throw new ArgumentNullException(nameof(configuration)); - } - if (hostingEnvironment == null) - { - throw new ArgumentNullException(nameof(hostingEnvironment)); - } - if (loggerFactory == null) - { - throw new ArgumentNullException(nameof(loggerFactory)); - } - - Configuration = configuration; - HostingEnvironment = hostingEnvironment; - Logger = loggerFactory.CreateLogger(GetType()); - } - - /// - /// Gets the recommended for all - /// instances. The recommended filter sequence is - /// - /// - /// Confirm signature or code query parameter e.g. in or other - /// subclass. - /// - /// - /// Confirm required headers, entries and query parameters are provided (in - /// ). - /// - /// - /// Short-circuit GET or HEAD requests, if receiver supports either (in ). - /// - /// Confirm it's a POST request (in ). - /// Confirm body type (in ). - /// - /// Map event name(s), if not done in for this receiver (in - /// ). - /// - /// - /// Short-circuit ping requests, if not done in for this receiver (in - /// ). - /// - /// - /// - public static int Order => -500; - - /// - /// Gets the for the application. - /// - protected IConfiguration Configuration; - - /// - /// Gets the . - /// - protected IHostingEnvironment HostingEnvironment { get; } - - /// - /// Gets an for use in this class and any subclasses. - /// - /// - /// Methods in this class use s that should be distinct from (higher than) those used in - /// subclasses. - /// - protected ILogger Logger { get; } - - /// - /// Some WebHooks rely on HTTPS for sending WebHook requests in a secure manner. A - /// subclass can call this method to ensure that the incoming WebHook - /// request is using HTTPS. If the request is not using HTTPS an error will be generated and the request will - /// not be further processed. - /// - /// - /// This method allows HTTP requests while the application is in development or if the - /// is . - /// - /// The name of an available . - /// The current . - /// - /// in the success case. When a check fails, an that when - /// executed will produce a response containing details about the problem. - /// - protected virtual IActionResult EnsureSecureConnection(string receiverName, HttpRequest request) - { - if (request == null) - { - throw new ArgumentNullException(nameof(request)); - } - - // Check to see if we have been configured to ignore this check. - var disableHttpsCheckString = Configuration[WebHookConstants.DisableHttpsCheckConfigurationKey]; - if (HostingEnvironment.IsDevelopment() || - (bool.TryParse(disableHttpsCheckString, out var disableHttpsCheck) && disableHttpsCheck)) - { - return null; - } - - // Require HTTPS. - if (!request.IsHttps) - { - Logger.LogError( - 500, - "The '{ReceiverName}' WebHook receiver requires {UpperSchemeName} in order to be secure. " + - "Please register a WebHook URI of type '{SchemeName}'.", - receiverName, - Uri.UriSchemeHttps.ToUpper(), - Uri.UriSchemeHttps); - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.Security_NoHttps, - receiverName, - Uri.UriSchemeHttps.ToUpper(), - Uri.UriSchemeHttps); - var noHttps = new BadRequestObjectResult(message); - - return noHttps; - } - - return null; - } - - /// - /// Gets the locally configured WebHook secret key used to validate any signature header provided in a WebHook - /// request. - /// - /// - /// The key (relative to ) of the - /// containing the receiver-specific - /// . - /// Typically this is the name of the receiver e.g. github. - /// - /// - /// The for this request. A (potentially empty) ID value in this data allows a - /// subclass to support multiple senders with individual configurations. - /// - /// The minimum length of the key value. - /// The maximum length of the key value. - /// - /// The configured WebHook secret key. if the configuration value does not exist. - /// - protected virtual string GetSecretKey( - string sectionKey, - RouteData routeData, - int minLength, - int maxLength) - { - if (sectionKey == null) - { - throw new ArgumentNullException(nameof(sectionKey)); - } - if (routeData == null) - { - throw new ArgumentNullException(nameof(routeData)); - } - - // Look up configuration for this receiver and instance. - var secrets = GetSecretKeys(sectionKey, routeData); - if (!secrets.Exists()) - { - return null; - } - - var secret = secrets.Value; - if (secret == null) - { - // Strange case: User incorrectly configured this id with sub-keys. - return null; - } - - if (secret.Length < minLength || secret.Length > maxLength) - { - // Secrete key found but it does not meet the length requirements. - routeData.TryGetWebHookReceiverId(out var id); - Logger.LogCritical( - 501, - "Could not find a valid configuration for the '{ReceiverName}' WebHook receiver, instance " + - "'{Id}'. The value must be between {MinLength} and {MaxLength} characters long.", - sectionKey, - id, - minLength, - maxLength); - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.Security_BadSecret, - sectionKey, - id, - minLength, - maxLength); - throw new InvalidOperationException(message); - } - - return secret; - } - - /// - /// Gets the locally configured WebHook secret keys used to validate any signature header provided in a WebHook - /// request. - /// - /// - /// The key (relative to ) of the - /// containing the receiver-specific - /// . - /// Typically this is the name of the receiver e.g. github. - /// - /// - /// The for this request. A (potentially empty) ID value in this data allows a - /// subclass to support multiple senders with individual configurations. - /// - /// - /// The containing the configured WebHook secret keys. - /// if the does not exist. - /// - protected virtual IConfigurationSection GetSecretKeys(string sectionKey, RouteData routeData) - { - if (sectionKey == null) - { - throw new ArgumentNullException(nameof(sectionKey)); - } - if (routeData == null) - { - throw new ArgumentNullException(nameof(routeData)); - } - - routeData.TryGetWebHookReceiverId(out var id); - - // Look up configuration for this receiver and instance - var secrets = GetSecretKeys(Configuration, sectionKey, id); - if (!secrets.Exists()) - { - if (!HasSecretKeys(Configuration, sectionKey)) - { - // No secret key configuration for this receiver at all. - Logger.LogCritical( - 502, - "Could not find a valid configuration for the '{ReceiverName}' WebHook receiver.", - sectionKey); - - var message = string.Format(CultureInfo.CurrentCulture, Resources.Security_NoSecrets, sectionKey); - throw new InvalidOperationException(message); - } - - // ID was not configured or the key length is invalid. Caller should treat null return value with a - // Not Found response. - Logger.LogError( - 503, - "Could not find a valid configuration for the '{ReceiverName}' WebHook receiver, instance '{Id}'.", - sectionKey, - id); - } - - return secrets; - } - - /// - /// Provides a time consistent comparison of two secrets in the form of two strings. - /// - /// The first secret to compare. - /// The second secret to compare. - /// - /// Returns if the two secrets are equal; otherwise. - /// - [MethodImpl(MethodImplOptions.NoOptimization)] - protected internal static bool SecretEqual(string inputA, string inputB) - { - if (ReferenceEquals(inputA, inputB)) - { - return true; - } - - if (inputA == null || inputB == null || inputA.Length != inputB.Length) - { - return false; - } - - var areSame = true; - for (var i = 0; i < inputA.Length; i++) - { - areSame &= inputA[i] == inputB[i]; - } - - return areSame; - } - - private static IConfigurationSection GetSecretKeys(IConfiguration configuration, string sectionKey, string id) - { - if (string.IsNullOrEmpty(id)) - { - id = WebHookConstants.DefaultIdConfigurationKey; - } - - // Look up configuration value for these keys. - var key = ConfigurationPath.Combine( - WebHookConstants.ReceiverConfigurationSectionKey, - sectionKey, - WebHookConstants.SecretKeyConfigurationKeySectionKey, - id); - - return configuration.GetSection(key); - } - - private static bool HasSecretKeys(IConfiguration configuration, string sectionKey) - { - var key = ConfigurationPath.Combine( - WebHookConstants.ReceiverConfigurationSectionKey, - sectionKey, - WebHookConstants.SecretKeyConfigurationKeySectionKey); - - return configuration.GetSection(key).Exists(); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookVerifyBodyTypeFilter.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookVerifyBodyTypeFilter.cs deleted file mode 100644 index b10baba..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookVerifyBodyTypeFilter.cs +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Globalization; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.AspNetCore.WebHooks.Properties; -using Microsoft.Extensions.Logging; -using Microsoft.Net.Http.Headers; - -namespace Microsoft.AspNetCore.WebHooks.Filters -{ - /// - /// An to allow only WebHook requests with a Content-Type matching - /// . - /// - /// - /// Done as an implementation and not an - /// because receivers do not dynamically vary their - /// . Use distinct values if different - /// configurations are needed for one receiver and the receiver's implements - /// . - /// - public class WebHookVerifyBodyTypeFilter : IResourceFilter, IOrderedFilter - { - private static readonly MediaTypeHeaderValue ApplicationJsonMediaType - = new MediaTypeHeaderValue("application/json"); - private static readonly MediaTypeHeaderValue ApplicationXmlMediaType - = new MediaTypeHeaderValue("application/xml"); - private static readonly MediaTypeHeaderValue TextJsonMediaType = new MediaTypeHeaderValue("text/json"); - private static readonly MediaTypeHeaderValue TextXmlMediaType = new MediaTypeHeaderValue("text/xml"); - - private readonly IWebHookBodyTypeMetadata _bodyTypeMetadata; - private readonly ILogger _logger; - - /// - /// Instantiates a new instance. - /// - /// The . - /// The . - public WebHookVerifyBodyTypeFilter(IWebHookBodyTypeMetadata bodyTypeMetadata, ILoggerFactory loggerFactory) - { - if (bodyTypeMetadata == null) - { - throw new ArgumentNullException(nameof(bodyTypeMetadata)); - } - if (loggerFactory == null) - { - throw new ArgumentNullException(nameof(loggerFactory)); - } - - _bodyTypeMetadata = bodyTypeMetadata; - _logger = loggerFactory.CreateLogger(); - } - - /// - /// Gets the used in all - /// instances. The recommended filter sequence is - /// - /// - /// Confirm signature or code query parameter e.g. in or other - /// subclass. - /// - /// - /// Confirm required headers, entries and query - /// parameters are provided (in ). - /// - /// - /// Short-circuit GET or HEAD requests, if receiver supports either (in ). - /// - /// Confirm it's a POST request (in ). - /// Confirm body type (in this filter). - /// - /// Short-circuit ping requests, if not done in for this receiver (in - /// ). - /// - /// - /// - public static int Order => WebHookVerifyMethodFilter.Order + 10; - - /// - int IOrderedFilter.Order => Order; - - /// - public void OnResourceExecuting(ResourceExecutingContext context) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var request = context.HttpContext.Request; - switch (_bodyTypeMetadata.BodyType) - { - case WebHookBodyType.Form: - if (!request.HasFormContentType) - { - context.Result = CreateUnsupportedMediaTypeResult(Resources.VerifyBody_NoFormData); - } - break; - - case WebHookBodyType.Json: - if (!IsJson(request)) - { - context.Result = CreateUnsupportedMediaTypeResult(Resources.VerifyBody_NoJson); - } - break; - - case WebHookBodyType.Xml: - if (!IsXml(request)) - { - context.Result = CreateUnsupportedMediaTypeResult(Resources.VerifyBody_NoXml); - } - break; - - default: - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.General_InvalidEnumValue, - nameof(WebHookBodyType), - _bodyTypeMetadata.BodyType); - throw new InvalidOperationException(message); - } - } - - /// - public void OnResourceExecuted(ResourceExecutedContext context) - { - // No-op - } - - /// - /// Determines whether the specified request contains JSON as indicated by a content type of - /// application/json, text/json or application/xyz+json. The term xyz can for - /// example be hal or some other JSON-derived media type. - /// - /// The to check. - /// - /// if the specified request contains JSON content; otherwise, . - /// - protected static bool IsJson(HttpRequest request) - { - if (request == null) - { - throw new ArgumentNullException(nameof(request)); - } - - var contentType = request.GetTypedHeaders().ContentType; - if (contentType == null) - { - return false; - } - - if (contentType.IsSubsetOf(ApplicationJsonMediaType) || contentType.IsSubsetOf(TextJsonMediaType)) - { - return true; - } - - // MVC's JsonInputFormatter does not support text/*+json by default. RFC 3023 and 6839 allow */*+json but - // https://www.iana.org/assignments/media-types/media-types.xhtml shows all +json registrations except - // model/gltf+json match application/*+json. - return contentType.Type.Equals("application", StringComparison.OrdinalIgnoreCase) && - contentType.SubType.EndsWith("+json", StringComparison.OrdinalIgnoreCase); - } - - /// - /// Determines whether the specified request contains XML as indicated by a content type of - /// application/xml, text/xml or application/xyz+xml. The term xyz can for example - /// be rdf or some other XML-derived media type. - /// - /// The to check. - /// - /// if the specified request contains XML content; otherwise, . - /// - protected static bool IsXml(HttpRequest request) - { - if (request == null) - { - throw new ArgumentNullException(nameof(request)); - } - - var contentType = request.GetTypedHeaders().ContentType; - if (contentType == null) - { - return false; - } - - if (contentType.IsSubsetOf(ApplicationXmlMediaType) || contentType.IsSubsetOf(TextXmlMediaType)) - { - return true; - } - - // MVC's XML input formatters do not support text/*+xml by default. RFC 3023 and 6839 allow */*+xml but - // https://www.iana.org/assignments/media-types/media-types.xhtml shows almost all +xml registrations - // match application/*+xml and none match text/*+xml. - return contentType.Type.Equals("application", StringComparison.OrdinalIgnoreCase) && - contentType.SubType.EndsWith("+xml", StringComparison.OrdinalIgnoreCase); - } - - private IActionResult CreateUnsupportedMediaTypeResult(string message) - { - _logger.LogInformation(0, message); - - var badMethod = new BadRequestObjectResult(message) - { - StatusCode = StatusCodes.Status415UnsupportedMediaType - }; - - return badMethod; - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookVerifyCodeFilter.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookVerifyCodeFilter.cs deleted file mode 100644 index d8c8f84..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookVerifyCodeFilter.cs +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.AspNetCore.WebHooks.Properties; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Primitives; - -namespace Microsoft.AspNetCore.WebHooks.Filters -{ - /// - /// An that verifies the code query parameter. Short-circuits the request if - /// the code query parameter is missing or does not match the receiver's configuration. Also confirms the - /// request URI uses the HTTPS scheme. - /// - public class WebHookVerifyCodeFilter : WebHookSecurityFilter, IResourceFilter - { - private readonly IReadOnlyList _codeVerifierMetadata; - - /// - /// Instantiates a new instance. - /// - /// - /// The used to initialize . - /// - /// - /// The used to initialize - /// . - /// - /// - /// The used to initialize . - /// - /// The collection of services. - public WebHookVerifyCodeFilter( - IConfiguration configuration, - IHostingEnvironment hostingEnvironment, - ILoggerFactory loggerFactory, - IEnumerable metadata) - : base(configuration, hostingEnvironment, loggerFactory) - { - _codeVerifierMetadata = metadata.OfType().ToArray(); - } - - /// - public void OnResourceExecuting(ResourceExecutingContext context) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var routeData = context.RouteData; - if (routeData.TryGetWebHookReceiverName(out var receiverName) && - _codeVerifierMetadata.Any(metadata => metadata.IsApplicable(receiverName))) - { - var result = EnsureValidCode(context.HttpContext.Request, routeData, receiverName); - if (result != null) - { - context.Result = result; - } - } - } - - /// - public void OnResourceExecuted(ResourceExecutedContext context) - { - // No-op - } - - /// - /// For WebHook providers with insufficient security considerations, the receiver can require that the WebHook - /// URI must be an https URI and contain a 'code' query parameter with a value configured for that - /// particular id. A sample WebHook URI is - /// 'https://{host}/api/webhooks/incoming/{receiver name}?code=83699ec7c1d794c0c780e49a5c72972590571fd8'. - /// The 'code' parameter must be between 32 and 128 characters long. - /// - /// The current . - /// - /// The for this request. A (potentially empty) ID value in this data allows a - /// to support multiple senders with individual configurations. - /// - /// The name of an available . - /// - /// in the success case. When a check fails, an that when - /// executed will produce a response containing details about the problem. - /// - protected virtual IActionResult EnsureValidCode( - HttpRequest request, - RouteData routeData, - string receiverName) - { - if (request == null) - { - throw new ArgumentNullException(nameof(request)); - } - if (routeData == null) - { - throw new ArgumentNullException(nameof(routeData)); - } - if (receiverName == null) - { - throw new ArgumentNullException(nameof(receiverName)); - } - - var result = EnsureSecureConnection(receiverName, request); - if (result != null) - { - return result; - } - - var code = request.Query[WebHookConstants.CodeQueryParameterName]; - if (StringValues.IsNullOrEmpty(code)) - { - Logger.LogError( - 400, - "A '{ReceiverName}' WebHook verification request must contain a '{ParameterName}' query " + - "parameter.", - receiverName, - WebHookConstants.CodeQueryParameterName); - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.General_NoQueryParameter, - receiverName, - WebHookConstants.CodeQueryParameterName); - var noCode = new BadRequestObjectResult(message); - - return noCode; - } - - var secretKey = GetSecretKey( - receiverName, - routeData, - WebHookConstants.CodeParameterMinLength, - WebHookConstants.CodeParameterMaxLength); - if (secretKey == null) - { - return new NotFoundResult(); - } - - if (!SecretEqual(code, secretKey)) - { - Logger.LogError( - 401, - "The '{ParameterName}' query parameter provided in the HTTP request did not match the " + - "expected value.", - WebHookConstants.CodeQueryParameterName); - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.VerifyCode_BadCode, - WebHookConstants.CodeQueryParameterName); - var invalidCode = new BadRequestObjectResult(message); - - return invalidCode; - } - - return null; - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookVerifyMethodFilter.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookVerifyMethodFilter.cs deleted file mode 100644 index f82e321..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookVerifyMethodFilter.cs +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Globalization; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.WebHooks.Properties; -using Microsoft.Extensions.Logging; - -namespace Microsoft.AspNetCore.WebHooks.Filters -{ - /// - /// An to allow only POST WebHook requests with a non-empty request body. To support - /// GET or HEAD requests the receiver project should implement - /// in its metadata service. - /// - /// - /// Done as an implementation and not an - /// because GET and HEAD requests (often pings or - /// simple verifications) are never of interest in user code. - /// - public class WebHookVerifyMethodFilter : IResourceFilter - { - private readonly ILogger _logger; - - /// - /// Instantiates a new instance. - /// - /// The . - public WebHookVerifyMethodFilter(ILoggerFactory loggerFactory) - { - _logger = loggerFactory.CreateLogger(); - } - - /// - /// Gets the recommended for all - /// instances. The recommended filter sequence is - /// - /// - /// Confirm signature or code query parameter e.g. in or other - /// subclass. - /// - /// - /// Confirm required headers, entries and query parameters are provided (in - /// ). - /// - /// - /// Short-circuit GET or HEAD requests, if receiver supports either (in ). - /// - /// Confirm it's a POST request (in this filter). - /// Confirm body type (in ). - /// - /// Map event name(s), if not done in for this receiver (in - /// ). - /// - /// - /// Short-circuit ping requests, if not done in for this receiver (in - /// ). - /// - /// - /// - public static int Order => WebHookGetRequestFilter.Order + 10; - - /// - public void OnResourceExecuting(ResourceExecutingContext context) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var request = context.HttpContext.Request; - if (context.RouteData.TryGetWebHookReceiverName(out var receiverName) && - (request.Body == null || - !request.ContentLength.HasValue || - request.ContentLength.Value == 0L || - !HttpMethods.IsPost(request.Method))) - { - // Log about the issue and short-circuit remainder of the pipeline. - context.Result = CreateBadMethodResult(request.Method, receiverName); - } - } - - /// - public void OnResourceExecuted(ResourceExecutedContext context) - { - // No-op - } - - private IActionResult CreateBadMethodResult(string methodName, string receiverName) - { - _logger.LogError( - 0, - "The HTTP '{RequestMethod}' method is not supported by the '{ReceiverName}' WebHook receiver.", - methodName, - receiverName); - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.VerifyMethod_BadMethod, - methodName, - receiverName); - - var badMethod = new BadRequestObjectResult(message) - { - StatusCode = StatusCodes.Status405MethodNotAllowed - }; - - return badMethod; - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookVerifyRequiredValueFilter.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookVerifyRequiredValueFilter.cs deleted file mode 100644 index 7acbd4c..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookVerifyRequiredValueFilter.cs +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.AspNetCore.WebHooks.Properties; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Primitives; - -namespace Microsoft.AspNetCore.WebHooks.Filters -{ - /// - /// - /// An to verify required HTTP headers, entries - /// and query parameters are present in a WebHook request. Uses services to - /// determine the requirements for the requested WebHook receiver. - /// - /// - /// Short-circuits the request if required values are missing. The response in that case will have a 400 - /// "Bad Request" status code. - /// - /// - /// - /// The , and - /// subclasses also verify required HTTP headers and query - /// parameters. But, none of those constraints and filters use information. - /// - public class WebHookVerifyRequiredValueFilter : IResourceFilter - { - private readonly ILogger _logger; - private readonly IReadOnlyList _bindingMetadata; - - /// - /// Instantiates a new instance. - /// - /// The . - /// The collection of services. - public WebHookVerifyRequiredValueFilter(ILoggerFactory loggerFactory, IEnumerable metadata) - { - _logger = loggerFactory.CreateLogger(); - _bindingMetadata = metadata.OfType().ToArray(); - } - - /// - /// Gets the recommended for all - /// instances. The recommended filter sequence is - /// - /// - /// Confirm signature or code query parameter e.g. in or other - /// subclass. - /// - /// - /// Confirm required headers, entries and query parameters are provided (in - /// this filter). - /// - /// - /// Short-circuit GET or HEAD requests, if receiver supports either (in ). - /// - /// Confirm it's a POST request (in ). - /// Confirm body type (in ). - /// - /// Map event name(s), if not done in for this receiver (in - /// ). - /// - /// - /// Short-circuit ping requests, if not done in for this receiver (in - /// ). - /// - /// - /// - public static int Order => WebHookSecurityFilter.Order + 10; - - /// - public void OnResourceExecuting(ResourceExecutingContext context) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var routeData = context.RouteData; - if (!routeData.TryGetWebHookReceiverName(out var receiverName)) - { - // Not a WebHook request. - return; - } - - var bindingMetadata = _bindingMetadata.FirstOrDefault(metadata => metadata.IsApplicable(receiverName)); - if (bindingMetadata == null) - { - // Receiver has no additional parameters. - return; - } - - var request = context.HttpContext.Request; - for (var i = 0; i < bindingMetadata.Parameters.Count; i++) - { - var parameter = bindingMetadata.Parameters[i]; - if (parameter.IsRequired) - { - bool found; - string message; - var sourceName = parameter.SourceName; - switch (parameter.ParameterType) - { - case WebHookParameterType.Header: - found = VerifyHeader(request.Headers, sourceName, receiverName, out message); - break; - - case WebHookParameterType.RouteValue: - found = VerifyRouteData(routeData, sourceName, receiverName, out message); - break; - - case WebHookParameterType.QueryParameter: - found = VerifyQueryParameter(request.Query, sourceName, receiverName, out message); - break; - - default: - message = string.Format( - CultureInfo.CurrentCulture, - Resources.General_InvalidEnumValue, - nameof(WebHookParameterType), - parameter.ParameterType); - throw new InvalidOperationException(message); - } - - if (!found) - { - // Do not return after first error. Instead log about all issues. - context.Result = new BadRequestObjectResult(message); - } - } - } - } - - /// - public void OnResourceExecuted(ResourceExecutedContext context) - { - // No-op - } - - private bool VerifyRouteData(RouteData routeData, string keyName, string receiverName, out string message) - { - if (routeData.Values.TryGetValue(keyName, out var value) && !string.IsNullOrEmpty(value as string)) - { - message = null; - return true; - } - - _logger.LogError( - 500, - "A '{ReceiverName}' WebHook request must contain a '{KeyName}' value in the route data.", - receiverName, - keyName); - message = string.Format( - CultureInfo.CurrentCulture, - Resources.VerifyRequiredValue_NoRouteValue, - receiverName, - keyName); - - return false; - } - - private bool VerifyHeader( - IHeaderDictionary headers, - string headerName, - string receiverName, - out string message) - { - if (headers.TryGetValue(headerName, out var values) && !StringValues.IsNullOrEmpty(values)) - { - message = null; - return true; - } - - _logger.LogError( - 501, - "A '{ReceiverName}' WebHook request must contain a '{HeaderName}' HTTP header.", - receiverName, - headerName); - message = string.Format( - CultureInfo.CurrentCulture, - Resources.VerifyRequiredValue_NoHeader, - receiverName, - headerName); - - return false; - } - - private bool VerifyQueryParameter( - IQueryCollection query, - string parameterName, - string receiverName, - out string message) - { - if (query.TryGetValue(parameterName, out var values) && !StringValues.IsNullOrEmpty(values)) - { - message = null; - return true; - } - - _logger.LogError( - 502, - "A '{ReceiverName}' WebHook request must contain a '{QueryParameterName}' query parameter.", - receiverName, - parameterName); - message = string.Format( - CultureInfo.CurrentCulture, - Resources.General_NoQueryParameter, - receiverName, - parameterName); - - return false; - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookVerifySignatureFilter.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookVerifySignatureFilter.cs deleted file mode 100644 index 3c3e583..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookVerifySignatureFilter.cs +++ /dev/null @@ -1,349 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.IO; -using System.Runtime.CompilerServices; -using System.Security.Cryptography; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.WebHooks.Properties; -using Microsoft.AspNetCore.WebHooks.Utilities; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; - -namespace Microsoft.AspNetCore.WebHooks.Filters -{ - /// - /// Base class for and or - /// implementations that verify request body content e.g. filters - /// that verify signatures of request body content. Subclasses should have an - /// equal to . - /// - public abstract class WebHookVerifySignatureFilter : WebHookSecurityFilter, IWebHookReceiver - { - /// - /// Instantiates a new instance. - /// - /// - /// The used to initialize . - /// - /// - /// The used to initialize - /// . - /// - /// - /// The used to initialize . - /// - protected WebHookVerifySignatureFilter( - IConfiguration configuration, - IHostingEnvironment hostingEnvironment, - ILoggerFactory loggerFactory) - : base(configuration, hostingEnvironment, loggerFactory) - { - } - - /// - public abstract string ReceiverName { get; } - - /// - public bool IsApplicable(string receiverName) - { - if (receiverName == null) - { - throw new ArgumentNullException(nameof(receiverName)); - } - - return string.Equals(ReceiverName, receiverName, StringComparison.OrdinalIgnoreCase); - } - - /// - /// Converts a hex-encoded string to a . - /// - /// THe hex-encoded string to convert. - /// The converted . - protected static byte[] FromHex(string content) - { - if (string.IsNullOrEmpty(content)) - { - return Array.Empty(); - } - - byte[] data = null; - try - { - data = new byte[content.Length / 2]; - var input = 0; - for (var output = 0; output < data.Length; output++) - { - data[output] = Convert.ToByte(new string(new char[2] { content[input++], content[input++] }), 16); - } - - if (input != content.Length) - { - data = null; - } - } - catch - { - data = null; - } - - if (data == null) - { - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.VerifySignature_InvalidHexValue, - content); - throw new InvalidOperationException(message); - } - - return data; - } - - /// - /// Provides a time consistent comparison of two secrets in the form of two byte arrays. - /// - /// The first secret to compare. - /// The second secret to compare. - /// if the two secrets are equal; otherwise. - [MethodImpl(MethodImplOptions.NoOptimization)] - protected static bool SecretEqual(byte[] inputA, byte[] inputB) - { - if (ReferenceEquals(inputA, inputB)) - { - return true; - } - - if (inputA == null || inputB == null || inputA.Length != inputB.Length) - { - return false; - } - - var areSame = true; - for (var i = 0; i < inputA.Length; i++) - { - areSame &= inputA[i] == inputB[i]; - } - - return areSame; - } - - /// - /// Gets the value of a given HTTP request . If the field is either not present in - /// the or has more than one value then an error is generated and returned in - /// . - /// - /// The current . - /// The name of the HTTP request header to look up. - /// - /// Set to in the success case. When a check fails, an that - /// when executed will produce a response containing details about the problem. - /// - /// The signature header; if this cannot be found. - [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Disposed by caller")] - protected virtual string GetRequestHeader( - HttpRequest request, - string headerName, - out IActionResult errorResult) - { - if (request == null) - { - throw new ArgumentNullException(nameof(request)); - } - if (headerName == null) - { - throw new ArgumentNullException(nameof(headerName)); - } - - if (!request.Headers.TryGetValue(headerName, out var headers) || headers.Count != 1) - { - var headersCount = headers.Count; - Logger.LogInformation( - 400, - "Expecting exactly one '{HeaderName}' header field in the WebHook request but found " + - "{HeaderCount}. Please ensure the request contains exactly one '{HeaderName}' header field.", - headerName, - headersCount, - headerName); - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.VerifySignature_BadHeader, - headerName, - headersCount); - errorResult = new BadRequestObjectResult(message); - - return null; - } - - errorResult = null; - - return headers; - } - - /// - /// Returns the SHA1 HMAC of the given 's body. - /// - /// The current . - /// The key data used to initialize the . - /// - /// A that on completion provides a array containing the SHA1 HMAC of the - /// 's body. - /// - protected virtual async Task GetRequestBodyHash_SHA1(HttpRequest request, byte[] secret) - { - await WebHookHttpRequestUtilities.PrepareRequestBody(request); - - using (var hasher = new HMACSHA1(secret)) - { - try - { - var hash = hasher.ComputeHash(request.Body); - return hash; - } - finally - { - // Reset Position because JsonInputFormatter et cetera always start from current position. - request.Body.Seek(0L, SeekOrigin.Begin); - } - } - } - - /// - /// Returns the SHA256 HMAC of the given 's body. - /// - /// The current . - /// The key data used to initialize the . - /// - /// A that on completion provides a array containing the SHA256 HMAC of - /// the 's body. - /// - protected Task GetRequestBodyHash_SHA256(HttpRequest request, byte[] secret) - { - return GetRequestBodyHash_SHA256(request, secret, prefix: null); - } - - /// - /// Returns the SHA256 HMAC of the given (if non-) followed by - /// the given 's body. - /// - /// The current . - /// The key data used to initialize the . - /// If non-, additional bytes to include in the hash. - /// - /// A that on completion provides a array containing the SHA256 HMAC of - /// the followed by the 's body. - /// - protected virtual async Task GetRequestBodyHash_SHA256( - HttpRequest request, - byte[] secret, - byte[] prefix) - { - await WebHookHttpRequestUtilities.PrepareRequestBody(request); - - using (var hasher = new HMACSHA256(secret)) - { - try - { - if (prefix != null && prefix.Length > 0) - { - hasher.TransformBlock( - inputBuffer: prefix, - inputOffset: 0, - inputCount: prefix.Length, - outputBuffer: null, - outputOffset: 0); - } - - var hash = hasher.ComputeHash(request.Body); - return hash; - } - finally - { - // Reset Position because JsonInputFormatter et cetera always start from current position. - request.Body.Seek(0L, SeekOrigin.Begin); - } - } - } - - /// - /// Decode the given . - /// - /// The hex-encoded . - /// - /// The name of the HTTP header containing the . - /// - /// - /// Set to if decoding is successful. Otherwise, an that - /// when executed will produce a response containing details about the problem. - /// - /// - /// If successful, the array containing the decoded hash. if any - /// issues occur. - /// - protected virtual byte[] GetDecodedHash( - string hexEncodedValue, - string signatureHeaderName, - out IActionResult errorResult) - { - try - { - var decodedHash = FromHex(hexEncodedValue); - errorResult = null; - - return decodedHash; - } - catch (Exception ex) - { - Logger.LogError( - 401, - ex, - "The '{HeaderName}' header value is invalid. It must be a valid hex-encoded string.", - signatureHeaderName); - } - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.VerifySignature_BadHeaderEncoding, - signatureHeaderName); - errorResult = new BadRequestObjectResult(message); - - return null; - } - - /// - /// Returns a new that when executed produces a response indicating that a - /// request had an invalid signature and as a result could not be processed. - /// - /// The name of an available . - /// The name of the HTTP header with invalid contents. - /// - /// An that when executed will produce a response with status code 400 "Bad - /// Request" and containing details about the problem. - /// - [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Disposed by caller")] - protected virtual IActionResult CreateBadSignatureResult(string receiverName, string signatureHeaderName) - { - Logger.LogError( - 402, - "The WebHook signature provided by the '{HeaderName}' header field does not match the value " + - "expected by the '{ReceiverName}' receiver. WebHook request is invalid.", - signatureHeaderName, - receiverName); - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.VerifySignature_BadSignature, - signatureHeaderName, - receiverName); - var badSignature = new BadRequestObjectResult(message); - - return badSignature; - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/GeneralWebHookAttribute.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/GeneralWebHookAttribute.cs deleted file mode 100644 index 5fcbc27..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/GeneralWebHookAttribute.cs +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Globalization; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.AspNetCore.WebHooks.Properties; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// - /// An indicating the associated action is a WebHook endpoint for all enabled receivers. - /// Specifies the expected , optional , and optional - /// . Also adds a for the - /// action. - /// - /// - /// The signature of the action should be: - /// - /// Task{IActionResult} ActionName(string receiverName, string id, string[] events, TData data) - /// - /// or the subset of parameters required. TData must be compatible with expected requests. - /// - /// - /// An example WebHook URI is 'https://{host}/api/webhooks/incoming/{receiver name}/{id}' or - /// 'https://{host}/api/webhooks/incoming/{receiver name}/{id}?code=94c0c780e49a5c72972590571fd8'. - /// - /// - /// - /// - /// If the application enables CORS in general (see the Microsoft.AspNetCore.Cors package), apply - /// DisableCorsAttribute to this action. If the application depends on the - /// Microsoft.AspNetCore.Mvc.ViewFeatures package, apply IgnoreAntiforgeryTokenAttribute to this - /// action. - /// - /// - /// should be used at most once per and - /// in a WebHook application. - /// - /// - public class GeneralWebHookAttribute : WebHookAttribute, IWebHookBodyTypeMetadata, IWebHookEventSelectorMetadata - { - private WebHookBodyType _bodyType = WebHookBodyType.Json; - private string _eventName; - - /// - /// Instantiates a new indicating the associated action is a WebHook - /// endpoint for all enabled receivers. - /// - public GeneralWebHookAttribute() - : base() - { - } - - /// - /// Default value is . - public WebHookBodyType BodyType - { - get - { - return _bodyType; - } - set - { - if (!Enum.IsDefined(typeof(WebHookBodyType), value)) - { - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.General_InvalidEnumValue, - nameof(WebHookBodyType), - value); - throw new ArgumentException(message, nameof(value)); - } - - _bodyType = value; - } - } - - /// - /// Gets or sets the name of the event the associated controller action accepts. - /// - /// Default value is , indicating this action accepts all events. - public string EventName - { - get - { - return _eventName; - } - set - { - if (string.IsNullOrEmpty(value)) - { - throw new ArgumentException(Resources.General_ArgumentCannotBeNullOrEmpty, nameof(value)); - } - - _eventName = value; - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/IWebHookReceiver.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/IWebHookReceiver.cs deleted file mode 100644 index 6ef41fe..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/IWebHookReceiver.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Provides an abstraction for processing incoming WebHooks from a particular WebHook generator, for example - /// Dropbox, GitHub, etc. All services and receiver-specific - /// filters should implement this interface. - /// - public interface IWebHookReceiver - { - /// - /// - /// Gets the case-insensitive name of the WebHook generator that this receiver supports, for example - /// dropbox or net. - /// - /// - /// The name provided here will map to a URI of the form - /// 'https://{host}/api/webhooks/incoming/{ReceiverName}'. - /// - /// - /// Should not return an empty string. - string ReceiverName { get; } - - /// - /// Gets an indication that this should execute in the current request. - /// - /// The name of an available . - /// - /// if this should execute; - /// otherwise. - /// - bool IsApplicable(string receiverName); - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/IWebHookRequestReader.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/IWebHookRequestReader.cs deleted file mode 100644 index 8dd0e22..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/IWebHookRequestReader.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Provides an abstraction for a service that parses the request body. For use in filters that execute prior to - /// regular model binding or in actions that read the request body after regular model binding. - /// - public interface IWebHookRequestReader - { - /// - /// Read the HTTP request entity body (formatted as HTML form URL-encoded data) as an - /// instance. - /// - /// The for the current request and action. - /// - /// A that on completion provides an instance containing data - /// from the HTTP request entity body. - /// - Task ReadAsFormDataAsync(ActionContext actionContext); - - /// - /// Read the HTTP request entity body as a instance. - /// - /// The type of data to return. - /// The for the current request and action. - /// - /// A that on completion provides a instance containing the - /// HTTP request entity body. - /// - Task ReadBodyAsync(ActionContext actionContext); - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Internal/WebHookRequestReader.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Internal/WebHookRequestReader.cs deleted file mode 100644 index 4fb58d5..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Internal/WebHookRequestReader.cs +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Internal; -using Microsoft.AspNetCore.Mvc.ModelBinding; -using Microsoft.AspNetCore.Mvc.ModelBinding.Binders; -using Microsoft.AspNetCore.WebHooks.Properties; -using Microsoft.AspNetCore.WebHooks.Utilities; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; - -namespace Microsoft.AspNetCore.WebHooks.Internal -{ - /// - /// The default implementation. - /// - public class WebHookRequestReader : IWebHookRequestReader - { - private readonly IModelBinder _bodyModelBinder; - private readonly IModelMetadataProvider _metadataProvider; - - /// - /// Instantiates a new instance. - /// - /// The . - /// The . - /// - /// The accessor for . - /// - /// The . - public WebHookRequestReader( - ILoggerFactory loggerFactory, - IModelMetadataProvider metadataProvider, - IOptions optionsAccessor, - IHttpRequestStreamReaderFactory readerFactory) - { - // Do not store options.ValueProviderFactories because that is only the initial value of (for example) - // ResourceExecutingContext.ValueProviderFactories. - var options = optionsAccessor.Value; - _bodyModelBinder = new BodyModelBinder(options.InputFormatters, readerFactory, loggerFactory, options); - _metadataProvider = metadataProvider; - } - - /// - public async Task ReadAsFormDataAsync(ActionContext actionContext) - { - if (actionContext == null) - { - throw new ArgumentNullException(nameof(actionContext)); - } - - var request = actionContext.HttpContext.Request; - if (!IsValidPost(request) || - !request.HasFormContentType) - { - // Filters e.g. WebHookVerifyBodyTypeFilter will log and return errors about these conditions. - return null; - } - - // ReadFormAsync does not always ensure the body can be read multiple times. - await WebHookHttpRequestUtilities.PrepareRequestBody(request); - - // Read request body. - IFormCollection formCollection; - try - { - formCollection = await request.ReadFormAsync(); - } - finally - { - request.Body.Seek(0L, SeekOrigin.Begin); - } - - return formCollection; - } - - /// - /// This method assumes the necessary input formatters have been registered. - public async Task ReadBodyAsync(ActionContext actionContext) - { - if (actionContext == null) - { - throw new ArgumentNullException(nameof(actionContext)); - } - - var request = actionContext.HttpContext.Request; - if (!IsValidPost(request)) - { - // Filters e.g. WebHookVerifyBodyTypeFilter will log and return errors about these conditions. - return default; - } - - var modelMetadata = _metadataProvider.GetMetadataForType(typeof(TModel)); - var bindingContext = DefaultModelBindingContext.CreateBindingContext( - actionContext, - new CompositeValueProvider(), - modelMetadata, - bindingInfo: null, - modelName: WebHookConstants.ModelStateBodyModelName); - - // Read request body. - try - { - await _bodyModelBinder.BindModelAsync(bindingContext); - } - finally - { - request.Body.Seek(0L, SeekOrigin.Begin); - } - - if (!bindingContext.ModelState.IsValid) - { - return default; - } - - if (!bindingContext.Result.IsModelSet) - { - throw new InvalidOperationException(Resources.RequestReader_ModelBindingFailed); - } - - // Success - return (TModel)bindingContext.Result.Model; - } - - private bool IsValidPost(HttpRequest request) - { - return request.Body != null && - request.ContentLength.HasValue && - request.ContentLength.Value > 0L && - HttpMethods.IsPost(request.Method); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Internal/WebHookServiceCollectionSetup.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Internal/WebHookServiceCollectionSetup.cs deleted file mode 100644 index 3e51fc5..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Internal/WebHookServiceCollectionSetup.cs +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.ApplicationModels; -using Microsoft.AspNetCore.WebHooks.ApplicationModels; -using Microsoft.AspNetCore.WebHooks.Filters; -using Microsoft.AspNetCore.WebHooks.Routing; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Options; - -namespace Microsoft.AspNetCore.WebHooks.Internal -{ - /// - /// Methods to add services for WebHook receivers. - /// - public static class WebHookServiceCollectionSetup - { - private static readonly Dictionary SingletonFilters = new Dictionary - { - { typeof(WebHookGetRequestFilter), WebHookGetRequestFilter.Order }, - { typeof(WebHookPingRequestFilter), WebHookPingRequestFilter.Order }, - { typeof(WebHookEventMapperFilter), WebHookEventMapperFilter.Order }, - { typeof(WebHookVerifyCodeFilter), WebHookSecurityFilter.Order }, - { typeof(WebHookVerifyMethodFilter), WebHookVerifyMethodFilter.Order }, - { typeof(WebHookVerifyRequiredValueFilter), WebHookVerifyRequiredValueFilter.Order }, - }; - - /// - /// Add services for WebHook receivers. - /// - /// The to update. - public static void AddWebHookServices(IServiceCollection services) - { - if (services == null) - { - throw new ArgumentNullException(nameof(services)); - } - - services.TryAddEnumerable( - ServiceDescriptor.Transient, MvcOptionsSetup>()); - - services.TryAddEnumerable( - ServiceDescriptor.Transient()); - services.TryAddEnumerable( - ServiceDescriptor.Transient()); - services.TryAddEnumerable( - ServiceDescriptor.Transient()); - - services.TryAddSingleton(); - services.TryAddSingleton(); - - services.TryAddSingleton(); - services.TryAddSingleton(); - - foreach (var keyValuePair in SingletonFilters) - { - services.TryAddSingleton(keyValuePair.Key); - } - } - - private class MvcOptionsSetup : IConfigureOptions - { - /// - public void Configure(MvcOptions options) - { - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } - - foreach (var keyValuePair in SingletonFilters) - { - options.Filters.AddService(keyValuePair.Key, keyValuePair.Value); - } - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookBindingMetadata.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookBindingMetadata.cs deleted file mode 100644 index b38e32a..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookBindingMetadata.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// - /// Metadata describing additional action parameters supported on a per-receiver basis. Implemented in a - /// service for receivers that support additional action parameters. - /// - /// - /// sets - /// properties based on this metadata and . - /// performs request validation based on this metadata, - /// in particular. - /// - /// - /// - /// Separate from because these bindings do not support constant values or - /// fall backs. Separate from because the information cannot be changed on a - /// per-action basis; a service must provide this metadata. - /// - public interface IWebHookBindingMetadata : IWebHookMetadata, IWebHookReceiver - { - /// - /// Gets the collection of s. - /// - /// Should not return . - IReadOnlyList Parameters { get; } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookBodyTypeMetadata.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookBodyTypeMetadata.cs deleted file mode 100644 index e61ec78..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookBodyTypeMetadata.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// - /// Metadata describing the request body type an action expects. Must be implemented in a protocol-specific - /// subclass or a registered service. For services, - /// see in particular. - /// - /// - /// sets - /// properties based on this metadata and . - /// confirms the request body type based on this metadata. - /// - /// - public interface IWebHookBodyTypeMetadata : IWebHookMetadata - { - /// - /// Gets the this receiver or specific action requires. - /// - WebHookBodyType BodyType { get; } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookBodyTypeMetadataService.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookBodyTypeMetadataService.cs deleted file mode 100644 index e5f8e71..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookBodyTypeMetadataService.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// Metadata describing the request body type an action expects. service - /// implementations that contain this information must implement this interface and not just - /// . - /// - public interface IWebHookBodyTypeMetadataService : IWebHookBodyTypeMetadata, IWebHookReceiver - { - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookEventFromBodyMetadata.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookEventFromBodyMetadata.cs deleted file mode 100644 index 834193a..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookEventFromBodyMetadata.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// - /// Metadata describing the source within the request body of a WebHook or string[] - /// action parameter named action parameter named action, @event, eventNames, or similar. - /// Implemented in a service for receivers that place event names in the body and - /// do not special-case event name mapping. Receivers using this metadata must also provide an - /// service. - /// - /// - /// maps event names based on this metadata. - /// - /// - /// - /// Receivers must not provide both this metadata and an service. - /// - public interface IWebHookEventFromBodyMetadata : IWebHookMetadata, IWebHookReceiver - { - /// - /// Gets an indication whether missing event names (no match in the request) - /// should be allowed. - /// - /// - /// If , requests lacking event names are allowed. Otherwise, - /// short-circuits the request, responding with a 400 "Bad - /// Request" status code. - /// - bool AllowMissing { get; } - - /// - /// Gets the property name, JSON path, or XPath used to read event names - /// from the request body. Interpretation depends on the of - /// the receiver. - /// - /// Should not return an empty string or . - string BodyPropertyPath { get; } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookEventMetadata.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookEventMetadata.cs deleted file mode 100644 index 09279b7..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookEventMetadata.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// - /// Metadata describing the source of a WebHook or string[] action parameter named - /// action, @event, eventNames, or similar. Implemented in a - /// service for receivers that do not place event names in the request body or special-case event name mapping. - /// - /// - /// maps event names based on this metadata. - /// - /// - /// - /// Receivers must not provide both this metadata and an service. - /// - public interface IWebHookEventMetadata : IWebHookMetadata, IWebHookReceiver - { - /// - /// Gets the constant event name for this receiver. Used as a fallback when and - /// are or do not match the request. - /// - /// Should not return an empty string. - string ConstantValue { get; } - - /// - /// Gets the name of the header containing event name(s) for this receiver. The named header is checked before - /// if both are non-. - /// - /// Should not return an empty string. - string HeaderName { get; } - - /// - /// Gets the name of the query parameter containing event name(s) for this receiver. The named query parameter - /// is checked after if both are non-. - /// - /// Should not return an empty string. - string QueryParameterName { get; } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookEventSelectorMetadata.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookEventSelectorMetadata.cs deleted file mode 100644 index d5a283f..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookEventSelectorMetadata.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// - /// Metadata describing a WebHook action which accepts only events named . Implemented in a - /// subclass for receivers that support multiple events and do not place event - /// information in the request body. Receivers using this metadata must also provide an - /// service. - /// - /// - /// The subclasses perform action selection based on this - /// metadata. - /// - /// - public interface IWebHookEventSelectorMetadata : IWebHookMetadata - { - /// - /// Gets the name of the event the associated controller action accepts. - /// - /// - /// Should not return an empty string. indicates associated action accepts all events. - /// - string EventName { get; } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookGetRequestMetadata.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookGetRequestMetadata.cs deleted file mode 100644 index a69b312..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookGetRequestMetadata.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// - /// Metadata indicating the receiver should confirm an appropriate secret key is configured and respond - /// successfully to an HTTP GET request. When is - /// non-, also indicates the response should contain the value of the - /// query parameter. Implemented in a - /// service for receivers that accept GET requests. - /// - /// - /// performs verifications and short-circuits GET requests based - /// on this metadata. Requests for receivers that do not implement reach - /// the . returns - /// a response with status code 405, "Method Not Allowed" for all non-POST requests. - /// - /// - /// - /// The secret key confirmation is particularly important for receivers secured using the request body (for - /// example, receivers that verify signatures). - /// - public interface IWebHookGetRequestMetadata : IWebHookMetadata, IWebHookReceiver - { - /// - /// Gets the name of a query parameter containing a value to include in the response to an HTTP GET request. - /// If non-, the request must contain this query parameter and the receiver responds - /// with its value in the body. Otherwise, the receiver responds to an HTTP GET request with an empty - /// response body. - /// - /// Should not return an empty string. - string ChallengeQueryParameterName { get; } - - /// - /// Gets the minimum length of the secret key configured for this receiver. Used to confirm the secret key is - /// property configured before responding to an HTTP GET request. - /// - int SecretKeyMinLength { get; } - - /// - /// Gets the maximum length of the secret key configured for this receiver. Used to confirm the secret key is - /// property configured before responding to an HTTP GET request. - /// - int SecretKeyMaxLength { get; } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookMetadata.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookMetadata.cs deleted file mode 100644 index 5f6f75d..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookMetadata.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// Marker interface for all WebHook metadata. Receivers must register a class that implements both - /// and whether or not an implementation of an - /// sub-interface is needed. - /// - public interface IWebHookMetadata - { - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookPingRequestMetadata.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookPingRequestMetadata.cs deleted file mode 100644 index 9a7a24b..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookPingRequestMetadata.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// - /// Metadata describing the event name for ping requests. Implemented in a service - /// for receivers that accept ping requests. - /// - /// - /// The subclasses select a default action (when a ping request - /// would not otherwise match) based on this metadata. - /// short-circuits ping requests based on this metadata. - /// - /// - public interface IWebHookPingRequestMetadata : IWebHookMetadata, IWebHookReceiver - { - /// - /// Gets the name of the ping event for this receiver. - /// - /// Should not return an empty string or . - string PingEventName { get; } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookVerifyCodeMetadata.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookVerifyCodeMetadata.cs deleted file mode 100644 index c6edb0a..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/IWebHookVerifyCodeMetadata.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// - /// Marker metadata interface for receivers that require a code query parameter. That query parameter must - /// match the configured secret key. Implemented in a service for receivers that do - /// not include a specific subclass. - /// - /// - /// verifies the code query parameter based on the existence - /// of this metadata for the receiver. verifies at least one - /// receiver-specific filter exists unless this metadata exists for the receiver. - /// - /// - public interface IWebHookVerifyCodeMetadata : IWebHookMetadata, IWebHookReceiver - { - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/WebHookBodyType.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/WebHookBodyType.cs deleted file mode 100644 index d38edd6..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/WebHookBodyType.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// General description of the required request body for a WebHook controller action. - /// - /// Starts at 1 to ensure instances are initialized. - public enum WebHookBodyType - { - /// - /// Request must have content-type application/x-www-form-urlencoded. A bound data - /// parameter should have an associated [FromForm] attribute. - /// - Form = 1, - - /// - /// Request must have content-type application/json, text/json, or a subset. A bound - /// data parameter should have an associated [FromBody] attribute. - /// - Json, - - /// - /// Request must have content-type application/xml, text/xml, or a subset. A bound - /// data parameter should have an associated [FromBody] attribute. - /// - Xml, - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/WebHookMetadata.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/WebHookMetadata.cs deleted file mode 100644 index 8906470..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/WebHookMetadata.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.WebHooks.Properties; - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// Base class for services. - /// - public abstract class WebHookMetadata : IWebHookMetadata, IWebHookReceiver - { - /// - /// Instantiates a new with the given . - /// - /// The name of an available . - protected WebHookMetadata(string receiverName) - { - if (string.IsNullOrEmpty(receiverName)) - { - throw new ArgumentException(Resources.General_ArgumentCannotBeNullOrEmpty, nameof(receiverName)); - } - - ReceiverName = receiverName; - } - - /// - public string ReceiverName { get; } - - /// - bool IWebHookReceiver.IsApplicable(string receiverName) - { - if (receiverName == null) - { - throw new ArgumentNullException(nameof(receiverName)); - } - - if (ReceiverName == null) - { - return true; - } - - return string.Equals(ReceiverName, receiverName, StringComparison.OrdinalIgnoreCase); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/WebHookParameter.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/WebHookParameter.cs deleted file mode 100644 index 65a1b90..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/WebHookParameter.cs +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.AspNetCore.WebHooks.Properties; - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// Metadata describing an additional parameter supported in a receiver. - /// - public class WebHookParameter - { - /// - /// Initializes a new with the given , - /// and . is - /// when using this constructor. - /// - /// The name of an action parameter. - /// The of this parameter. - /// - /// The name of the HTTP header, entry or query parameter - /// containing this parameter's value. - /// - public WebHookParameter(string name, WebHookParameterType parameterType, string sourceName) - : this(name, parameterType, sourceName, isRequired: false) - { - } - - /// - /// Initializes a new with the given , - /// , , and . - /// - /// The name of an action parameter. - /// The of this parameter. - /// - /// The name of the HTTP header, entry or query parameter - /// containing this parameter's value. - /// - /// - /// Specifies whether the HTTP header, - /// entry or query parameter is required in a WebHook - /// request. - /// - public WebHookParameter(string name, WebHookParameterType parameterType, string sourceName, bool isRequired) - { - if (string.IsNullOrEmpty(name)) - { - throw new System.ArgumentException(Resources.General_ArgumentCannotBeNullOrEmpty, nameof(name)); - } - if (string.IsNullOrEmpty(sourceName)) - { - throw new System.ArgumentException(Resources.General_ArgumentCannotBeNullOrEmpty, nameof(sourceName)); - } - - Name = name; - ParameterType = parameterType; - SourceName = sourceName; - IsRequired = isRequired; - } - - /// - /// Gets the name of an action parameter. - /// - public string Name { get; } - - /// - /// Gets the of this parameter. - /// - public WebHookParameterType ParameterType { get; } - - /// - /// Gets the name of the HTTP header, entry or query - /// parameter containing this parameter's value. - /// - /// - public string SourceName { get; } - - /// - /// Gets an indication the HTTP header, - /// entry or query parameter is required in a WebHook - /// request. - /// - /// - /// If and the HTTP header - /// entry or query parameter is missing, the receiver - /// will respond with status code 400 "Bad Request". Otherwise, no additional validation is performed. - /// - public bool IsRequired { get; } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/WebHookParameterType.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/WebHookParameterType.cs deleted file mode 100644 index 216802b..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/WebHookParameterType.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.WebHooks.Metadata -{ - /// - /// Description of where a value is found and how - /// should be interpreted. - /// - /// Starts at 1 to ensure instances are initialized. - public enum WebHookParameterType - { - /// - /// value is found in the request headers. That is, - /// is a header name. - /// - Header = 1, - - /// - /// value is found in the . - /// That is, is a - /// key name. - /// - RouteValue, - - /// - /// value is found in the query string. That is, - /// is a query parameter name. - /// - QueryParameter, - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Microsoft.AspNetCore.WebHooks.Receivers.csproj b/src/Microsoft.AspNetCore.WebHooks.Receivers/Microsoft.AspNetCore.WebHooks.Receivers.csproj deleted file mode 100644 index 77d95ee..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Microsoft.AspNetCore.WebHooks.Receivers.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - $(Configurations);CodeAnalysis - ASP.NET Core WebHooks abstractions and infrastructure components for receivers. Contains constraints, filters, metadata, and the application models to apply them. - aspnetcore;webhook;receiver - - - - - Utilities\ObjectPathUtilities.cs - - - - - diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Properties/AssemblyInfo.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Properties/AssemblyInfo.cs deleted file mode 100644 index 0c3cf7f..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Microsoft.AspNetCore.WebHooks.Receivers.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Properties/Resources.Designer.cs deleted file mode 100644 index 877d93a..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Properties/Resources.Designer.cs +++ /dev/null @@ -1,333 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Microsoft.AspNetCore.WebHooks.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.AspNetCore.WebHooks.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to Invalid WebHook constraint configuration encountered. '{0}' executed though '{1}' should have disallowed the request.. - /// - internal static string EventConstraints_NoReceiverName { - get { - return ResourceManager.GetString("EventConstraints_NoReceiverName", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to A '{0}' WebHook request must contain a match for '{1}' in the HTTP request entity body indicating the type or types of event.. - /// - internal static string EventMapper_NoBodyProperty { - get { - return ResourceManager.GetString("EventMapper_NoBodyProperty", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Value cannot be null or empty.. - /// - internal static string General_ArgumentCannotBeNullOrEmpty { - get { - return ResourceManager.GetString("General_ArgumentCannotBeNullOrEmpty", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Enum type {0} has no defined '{1}' value.. - /// - internal static string General_InvalidEnumValue { - get { - return ResourceManager.GetString("General_InvalidEnumValue", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to A '{0}' WebHook request must contain a '{1}' query parameter.. - /// - internal static string General_NoQueryParameter { - get { - return ResourceManager.GetString("General_NoQueryParameter", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to A '{0}' WebHook verification request must contain a '{1}' query parameter.. - /// - internal static string GetRequest_NoQueryParameter { - get { - return ResourceManager.GetString("GetRequest_NoQueryParameter", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid metadata services found. Receivers must not provide both '{0}' and '{1}' services.. - /// - internal static string MetadataProvider_ConflictingMetadataServices { - get { - return ResourceManager.GetString("MetadataProvider_ConflictingMetadataServices", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Duplicate '{0}' registrations found.. - /// - internal static string MetadataProvider_DuplicateMetadata { - get { - return ResourceManager.GetString("MetadataProvider_DuplicateMetadata", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to '{0}' has a null {1} property but does not implement '{2}'.. - /// - internal static string MetadataProvider_MissingAttributeMetadata { - get { - return ResourceManager.GetString("MetadataProvider_MissingAttributeMetadata", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to No '{0}' implementation found for the '{1}' WebHook receiver.. - /// - internal static string MetadataProvider_MissingMetadata { - get { - return ResourceManager.GetString("MetadataProvider_MissingMetadata", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid metadata services found. Metadata services implementing '{0}' must also implement '{1}'.. - /// - internal static string MetadataProvider_MissingMetadataServices { - get { - return ResourceManager.GetString("MetadataProvider_MissingMetadataServices", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid metadata services found for the '{0}' WebHook receiver. Receivers with attributes implementing '{1}' must also provide a '{2}' service.. - /// - internal static string MetadataProvider_MissingMetadataServicesForReceiver { - get { - return ResourceManager.GetString("MetadataProvider_MissingMetadataServicesForReceiver", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid metadata services found. Metadata services implementing '{0}' must implement '{1}'.. - /// - internal static string MetadataProvider_WrongInterface { - get { - return ResourceManager.GetString("MetadataProvider_WrongInterface", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The MVC model binding system failed. Model state is valid but model was not set.. - /// - internal static string RequestReader_ModelBindingFailed { - get { - return ResourceManager.GetString("RequestReader_ModelBindingFailed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The MVC model binding system unexpectedly failed. Binding the {0} type should never add {1} errors.. - /// - internal static string RequestReader_ModelBindingUnexpectedlyInvalid { - get { - return ResourceManager.GetString("RequestReader_ModelBindingUnexpectedlyInvalid", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to {0} and {1} were applied to the same action. {0} must not be combined with another attribute that provides a route template.. - /// - internal static string RoutingProvider_MixedRouteWithWebHookAttribute { - get { - return ResourceManager.GetString("RoutingProvider_MixedRouteWithWebHookAttribute", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Could not find a valid configuration for the '{0}' WebHook receiver, instance '{1}'. The value must be between {2} and {3} characters long.. - /// - internal static string Security_BadSecret { - get { - return ResourceManager.GetString("Security_BadSecret", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The '{0}' WebHook receiver requires {1} in order to be secure. Please register a WebHook URI of type '{2}'.. - /// - internal static string Security_NoHttps { - get { - return ResourceManager.GetString("Security_NoHttps", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Could not find a valid configuration for the '{0}' WebHook receiver. Please configure secret keys for this receiver.. - /// - internal static string Security_NoSecrets { - get { - return ResourceManager.GetString("Security_NoSecrets", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The WebHook request must contain an entity body formatted as HTML form URL-encoded data.. - /// - internal static string VerifyBody_NoFormData { - get { - return ResourceManager.GetString("VerifyBody_NoFormData", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The WebHook request must contain an entity body formatted as JSON.. - /// - internal static string VerifyBody_NoJson { - get { - return ResourceManager.GetString("VerifyBody_NoJson", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The WebHook request must contain an entity body formatted as XML.. - /// - internal static string VerifyBody_NoXml { - get { - return ResourceManager.GetString("VerifyBody_NoXml", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The '{0}' query parameter provided in the HTTP request did not match the expected value.. - /// - internal static string VerifyCode_BadCode { - get { - return ResourceManager.GetString("VerifyCode_BadCode", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The HTTP '{0}' method is not supported by the '{1}' WebHook receiver.. - /// - internal static string VerifyMethod_BadMethod { - get { - return ResourceManager.GetString("VerifyMethod_BadMethod", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to A '{0}' WebHook request must contain a '{1}' HTTP header.. - /// - internal static string VerifyRequiredValue_NoHeader { - get { - return ResourceManager.GetString("VerifyRequiredValue_NoHeader", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to A '{0}' WebHook request must contain a '{1}' value in the route data.. - /// - internal static string VerifyRequiredValue_NoRouteValue { - get { - return ResourceManager.GetString("VerifyRequiredValue_NoRouteValue", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Expecting exactly one '{0}' header field in the WebHook request but found {1}. Please ensure the request contains exactly one '{0}' header field.. - /// - internal static string VerifySignature_BadHeader { - get { - return ResourceManager.GetString("VerifySignature_BadHeader", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The '{0}' header value is invalid. It must be a valid hex-encoded string.. - /// - internal static string VerifySignature_BadHeaderEncoding { - get { - return ResourceManager.GetString("VerifySignature_BadHeaderEncoding", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The signature provided by the '{0}' header field does not match the value expected by the '{1}' WebHook receiver. WebHook request is invalid.. - /// - internal static string VerifySignature_BadSignature { - get { - return ResourceManager.GetString("VerifySignature_BadSignature", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Input is not a valid hex-encoded string: '{0}'. Please provide a valid hex-encoded string.. - /// - internal static string VerifySignature_InvalidHexValue { - get { - return ResourceManager.GetString("VerifySignature_InvalidHexValue", resourceCulture); - } - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Properties/Resources.resx b/src/Microsoft.AspNetCore.WebHooks.Receivers/Properties/Resources.resx deleted file mode 100644 index b66dc1d..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Properties/Resources.resx +++ /dev/null @@ -1,210 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Invalid WebHook constraint configuration encountered. '{0}' executed though '{1}' should have disallowed the request. - - - A '{0}' WebHook request must contain a match for '{1}' in the HTTP request entity body indicating the type or types of event. - - - Value cannot be null or empty. - - - Enum type {0} has no defined '{1}' value. - - - A '{0}' WebHook request must contain a '{1}' query parameter. - - - A '{0}' WebHook verification request must contain a '{1}' query parameter. - - - Invalid metadata services found. Receivers must not provide both '{0}' and '{1}' services. - - - Duplicate '{0}' registrations found. - - - '{0}' has a null {1} property but does not implement '{2}'. - - - No '{0}' implementation found for the '{1}' WebHook receiver. - - - Invalid metadata services found. Metadata services implementing '{0}' must also implement '{1}'. - - - Invalid metadata services found for the '{0}' WebHook receiver. Receivers with attributes implementing '{1}' must also provide a '{2}' service. - - - Invalid metadata services found. Metadata services implementing '{0}' must implement '{1}'. - - - The MVC model binding system failed. Model state is valid but model was not set. - - - The MVC model binding system unexpectedly failed. Binding the {0} type should never add {1} errors. - - - {0} and {1} were applied to the same action. {0} must not be combined with another attribute that provides a route template. - - - Could not find a valid configuration for the '{0}' WebHook receiver, instance '{1}'. The value must be between {2} and {3} characters long. - - - The '{0}' WebHook receiver requires {1} in order to be secure. Please register a WebHook URI of type '{2}'. - - - Could not find a valid configuration for the '{0}' WebHook receiver. Please configure secret keys for this receiver. - - - The WebHook request must contain an entity body formatted as HTML form URL-encoded data. - - - The WebHook request must contain an entity body formatted as JSON. - - - The WebHook request must contain an entity body formatted as XML. - - - The '{0}' query parameter provided in the HTTP request did not match the expected value. - - - The HTTP '{0}' method is not supported by the '{1}' WebHook receiver. - - - A '{0}' WebHook request must contain a '{1}' HTTP header. - - - A '{0}' WebHook request must contain a '{1}' value in the route data. - - - Expecting exactly one '{0}' header field in the WebHook request but found {1}. Please ensure the request contains exactly one '{0}' header field. - - - The '{0}' header value is invalid. It must be a valid hex-encoded string. - - - The signature provided by the '{0}' header field does not match the value expected by the '{1}' WebHook receiver. WebHook request is invalid. - - - Input is not a valid hex-encoded string: '{0}'. Please provide a valid hex-encoded string. - - \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookEventMapperConstraint.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookEventMapperConstraint.cs deleted file mode 100644 index b3be28a..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookEventMapperConstraint.cs +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc.ActionConstraints; -using Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.AspNetCore.WebHooks.Properties; -using Microsoft.Extensions.Logging; - -namespace Microsoft.AspNetCore.WebHooks.Routing -{ - /// - /// An implementation which uses to determine - /// the event name(s) for a WebHook request. This constraint accepts all candidates for receivers lacking - /// or with - /// non-. Otherwise, the request must contain one or more event names. - /// - public class WebHookEventMapperConstraint : IActionConstraint - { - private readonly IReadOnlyList _eventMetadata; - private readonly ILogger _logger; - - /// - /// Instantiates a new instance with the given - /// and . - /// - /// The . - /// The collection of services. - public WebHookEventMapperConstraint(ILoggerFactory loggerFactory, IEnumerable metadata) - { - _eventMetadata = metadata.OfType().ToArray(); - _logger = loggerFactory.CreateLogger(); - } - - /// - /// Gets the value used in all - /// instances. - /// - /// Chosen to run this constraint just after . - public static int Order => WebHookIdConstraint.Order + 10; - - /// - int IActionConstraint.Order => Order; - - /// - public bool Accept(ActionConstraintContext context) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var routeContext = context.RouteContext; - if (routeContext.RouteData.TryGetWebHookReceiverName(out var receiverName)) - { - var eventMetadata = _eventMetadata.FirstOrDefault(metadata => metadata.IsApplicable(receiverName)); - if (eventMetadata != null) - { - return Accept(eventMetadata, routeContext); - } - - // This receiver does not have IWebHookEventMetadata and that's fine. - return true; - } - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.EventConstraints_NoReceiverName, - typeof(WebHookEventMapperConstraint), - typeof(WebHookReceiverExistsConstraint)); - throw new InvalidOperationException(message); - } - - /// - /// Gets an indication whether the expected event names are available in the request. Maps the event names into - /// route values. - /// - /// The for this receiver. - /// The for this constraint and request. - /// - /// if event names are available in the request; otherwise. - /// - protected virtual bool Accept(IWebHookEventMetadata eventMetadata, RouteContext routeContext) - { - if (eventMetadata == null) - { - throw new ArgumentNullException(nameof(eventMetadata)); - } - - if (routeContext == null) - { - throw new ArgumentNullException(nameof(routeContext)); - } - - var request = routeContext.HttpContext.Request; - var routeData = routeContext.RouteData; - if (eventMetadata.HeaderName != null) - { - var headers = request.Headers; - - var events = headers.GetCommaSeparatedValues(eventMetadata.HeaderName); - if (events.Length > 0) - { - routeData.SetWebHookEventNames(events); - return true; - } - } - - if (eventMetadata.QueryParameterName != null) - { - var query = request.Query; - if (query.TryGetValue(eventMetadata.QueryParameterName, out var events) && - events.Count > 0) - { - routeData.SetWebHookEventNames(events); - return true; - } - } - - if (eventMetadata.ConstantValue != null) - { - routeData.Values[WebHookConstants.EventKeyName] = eventMetadata.ConstantValue; - return true; - } - - routeData.TryGetWebHookReceiverName(out var receiverName); - if (eventMetadata.QueryParameterName == null) - { - _logger.LogError( - 500, - "A '{ReceiverName}' WebHook request must contain a '{HeaderName}' HTTP header " + - "indicating the type of event.", - receiverName, - eventMetadata.HeaderName); - } - else if (eventMetadata.HeaderName == null) - { - _logger.LogError( - 501, - "A '{ReceiverName}' WebHook request must contain a '{QueryParameterKey}' query " + - "parameter indicating the type of event.", - receiverName, - eventMetadata.QueryParameterName); - } - else - { - _logger.LogError( - 502, - "A '{ReceiverName}' WebHook request must contain a '{HeaderName}' HTTP header or a " + - "'{QueryParameterKey}' query parameter indicating the type of event.", - receiverName, - eventMetadata.HeaderName, - eventMetadata.QueryParameterName); - } - - return false; - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookEventNamesConstraint.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookEventNamesConstraint.cs deleted file mode 100644 index 4ed2149..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookEventNamesConstraint.cs +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Linq; -using Microsoft.AspNetCore.Mvc.ActionConstraints; -using Microsoft.AspNetCore.Routing; - -namespace Microsoft.AspNetCore.WebHooks.Routing -{ - /// - /// A base class for implementations which use WebHook event names to select - /// candidate actions. - /// - public abstract class WebHookEventNamesConstraint : IActionConstraint - { - /// - /// Instantiates a new instance. - /// - protected WebHookEventNamesConstraint() - { - } - - // Running this constraint last avoids NotFound responses to ping requests because other actions have different - // constraints on them. - /// - /// Chosen to ensure constraints of this type run last. - public int Order => int.MaxValue; - - /// - public abstract bool Accept(ActionConstraintContext context); - - /// - /// Gets an indication the action is a valid candidate for selection. - /// - /// The . - /// The event name to match. - /// Name of the ping event this action expects, if any. - /// - /// if the action is valid for selection; otherwise. - /// - protected bool Accept(ActionConstraintContext context, string eventName, string pingEventName) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (context.RouteContext.RouteData.TryGetWebHookEventNames(out var eventNames)) - { - if (eventNames.Any(name => string.Equals(eventName, name, StringComparison.OrdinalIgnoreCase))) - { - // Simple case. Request is for the expected event. - return true; - } - - if (pingEventName != null && - eventNames.Any(name => string.Equals(pingEventName, name, StringComparison.OrdinalIgnoreCase))) - { - // Decide if this is the candidate that should support the ping event. Ping events must succeed - // even if all actions are for other event names. - // 1. Is this the first candidate? If not, never handle ping events. - if (context.Candidates[0].Action != context.CurrentCandidate.Action) - { - return false; - } - - // 2. Does another candidate lack this constraint? If yes, they'll handle ping events. - for (var i = 1; i < context.Candidates.Count; i++) - { - var candidate = context.Candidates[i]; - if (candidate.Constraints == null || - !candidate.Constraints.Any(constraint => constraint is WebHookEventNamesConstraint)) - { - return false; - } - } - - // 3. Is another candidate configured to accept this request? - for (var i = 1; i < context.Candidates.Count; i++) - { - var candidate = context.Candidates[i]; - var constraints = context.Candidates.OfType(); - var innerContext = new ActionConstraintContext - { - Candidates = context.Candidates, - CurrentCandidate = candidate, - RouteContext = context.RouteContext, - }; - - // Constraints shouldn't actually contain more than one instance. But, doesn't hurt to check. - if (constraints.All(constraint => constraint.Accept(innerContext))) - { - return false; - } - } - - // 4. No other candidate accepts ping events. It's up to us. - return true; - } - } - - return false; - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookIdConstraint.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookIdConstraint.cs deleted file mode 100644 index 93710c3..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookIdConstraint.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.Mvc.ActionConstraints; -using Microsoft.AspNetCore.Routing; - -namespace Microsoft.AspNetCore.WebHooks.Routing -{ - /// - /// An implementation which uses WebHook ids to select candidate actions. - /// - public class WebHookIdConstraint : IActionConstraint - { - private readonly string _id; - - /// - /// Instantiates a new with the given . - /// - /// The receiver id to match. - public WebHookIdConstraint(string id) - { - if (id == null) - { - throw new ArgumentNullException(nameof(id)); - } - - _id = id; - } - - /// - /// Gets the value used in all - /// instances. - /// - /// Chosen to run this constraint just after . - public static int Order => WebHookReceiverNameConstraint.Order + 10; - - /// - int IActionConstraint.Order => Order; - - /// - public bool Accept(ActionConstraintContext context) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (!context.RouteContext.RouteData.TryGetWebHookReceiverId(out var id)) - { - return false; - } - - return string.Equals(_id, id, StringComparison.OrdinalIgnoreCase); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookMultipleEventNamesConstraint.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookMultipleEventNamesConstraint.cs deleted file mode 100644 index 5797317..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookMultipleEventNamesConstraint.cs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using Microsoft.AspNetCore.Mvc.ActionConstraints; -using Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.WebHooks.Metadata; -using Microsoft.AspNetCore.WebHooks.Properties; - -namespace Microsoft.AspNetCore.WebHooks.Routing -{ - /// - /// An implementation which determines the appropriate - /// for a WebHook request. It then uses that metadata and a specified - /// event name to select candidate actions. - /// - public class WebHookMultipleEventNamesConstraint : WebHookEventNamesConstraint - { - private readonly string _eventName; - private readonly IReadOnlyList _pingMetadata; - - /// - /// Instantiates a new instance with the given - /// and . - /// - /// Name of the event this action expects. - /// The collection of services. - public WebHookMultipleEventNamesConstraint( - string eventName, - IReadOnlyList pingMetadata) - { - if (eventName == null) - { - throw new ArgumentNullException(nameof(eventName)); - } - if (pingMetadata == null) - { - throw new ArgumentNullException(nameof(pingMetadata)); - } - - _eventName = eventName; - _pingMetadata = pingMetadata; - } - - /// - public override bool Accept(ActionConstraintContext context) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (context.RouteContext.RouteData.TryGetWebHookReceiverName(out var receiverName)) - { - var pingMetadata = _pingMetadata.FirstOrDefault(metadata => metadata.IsApplicable(receiverName)); - return Accept(context, _eventName, pingMetadata?.PingEventName); - } - - var message = string.Format( - CultureInfo.CurrentCulture, - Resources.EventConstraints_NoReceiverName, - typeof(WebHookMultipleEventNamesConstraint), - typeof(WebHookReceiverExistsConstraint)); - throw new InvalidOperationException(message); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookReceiverExistsConstraint.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookReceiverExistsConstraint.cs deleted file mode 100644 index 72c4141..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookReceiverExistsConstraint.cs +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.AspNetCore.Mvc.ActionConstraints; -using Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.WebHooks.Metadata; - -namespace Microsoft.AspNetCore.WebHooks.Routing -{ - /// - /// An implementation which confirms an service - /// exists describing the receiver for the current request. - /// - public class WebHookReceiverExistsConstraint : IActionConstraint - { - private readonly IReadOnlyList _receiverMetadata; - - /// - /// Instantiates a new with the given . - /// - /// The collection of services. - public WebHookReceiverExistsConstraint(IEnumerable metadata) - { - _receiverMetadata = metadata.OfType().ToArray(); - } - - /// - /// Gets the value used in all - /// instances. - /// - /// Chosen to run this constraint early in action selection. - public static int Order => -500; - - /// - int IActionConstraint.Order => Order; - - /// - public bool Accept(ActionConstraintContext context) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (!context.RouteContext.RouteData.TryGetWebHookReceiverName(out var receiverName)) - { - return false; - } - - if (!_receiverMetadata.Any(receiver => receiver.IsApplicable(receiverName))) - { - return false; - } - - context.RouteContext.RouteData.Values[WebHookConstants.ReceiverExistsKeyName] = true; - - return true; - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookReceiverNameConstraint.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookReceiverNameConstraint.cs deleted file mode 100644 index 1ffb3cc..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookReceiverNameConstraint.cs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.Mvc.ActionConstraints; -using Microsoft.AspNetCore.Routing; - -namespace Microsoft.AspNetCore.WebHooks.Routing -{ - /// - /// An implementation which uses WebHook receiver names to select candidate - /// actions. - /// - public class WebHookReceiverNameConstraint : IActionConstraint - { - private readonly string _receiverName; - - /// - /// Instantiates a new with the given - /// . - /// - /// The receiver name to match. - public WebHookReceiverNameConstraint(string receiverName) - { - if (receiverName == null) - { - throw new ArgumentNullException(nameof(receiverName)); - } - - _receiverName = receiverName; - } - - /// - /// Gets the value used in all - /// instances. - /// - /// Chosen to run this constraint just after . - public static int Order => WebHookReceiverExistsConstraint.Order + 10; - - /// - int IActionConstraint.Order => Order; - - /// - public bool Accept(ActionConstraintContext context) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (!context.RouteContext.RouteData.TryGetWebHookReceiverName(out var receiverName)) - { - return false; - } - - return string.Equals(_receiverName, receiverName, StringComparison.OrdinalIgnoreCase); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookSingleEventNamesConstraint.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookSingleEventNamesConstraint.cs deleted file mode 100644 index 2821b60..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Routing/WebHookSingleEventNamesConstraint.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.Mvc.ActionConstraints; - -namespace Microsoft.AspNetCore.WebHooks.Routing -{ - /// - /// An implementations which uses WebHook event names to select candidate actions. - /// - public class WebHookSingleEventNamesConstraint : WebHookEventNamesConstraint - { - private readonly string _eventName; - private readonly string _pingEventName; - - /// - /// Instantiates a new instance with the given - /// and . - /// - /// The event name to match. - /// Name of the ping event this action expects, if any. - public WebHookSingleEventNamesConstraint(string eventName, string pingEventName) - { - if (eventName == null) - { - throw new ArgumentNullException(nameof(eventName)); - } - - _eventName = eventName; - - // No need for extra handling if this constraint is for the ping event. - if (!string.Equals(_eventName, _pingEventName, StringComparison.OrdinalIgnoreCase)) - { - _pingEventName = pingEventName; - } - } - - /// - public override bool Accept(ActionConstraintContext context) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - return Accept(context, _eventName, _pingEventName); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/Utilities/WebHookHttpRequestUtilities.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/Utilities/WebHookHttpRequestUtilities.cs deleted file mode 100644 index bebb970..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/Utilities/WebHookHttpRequestUtilities.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Diagnostics; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Internal; -using Microsoft.AspNetCore.WebUtilities; - -namespace Microsoft.AspNetCore.WebHooks.Utilities -{ - /// - /// Utility methods related to instances. - /// - internal static class WebHookHttpRequestUtilities - { - /// - /// Ensure we can read the body without messing up JSON etc. deserialization. Body - /// will be read at least twice in most WebHook receivers. - /// - /// The to prepare. - /// A that on completion will have prepared the request body. - public static async Task PrepareRequestBody(HttpRequest request) - { - if (request == null) - { - throw new ArgumentNullException(nameof(request)); - } - - if (!request.Body.CanSeek) - { - BufferingHelper.EnableRewind(request); - Debug.Assert(request.Body.CanSeek); - - await request.Body.DrainAsync(CancellationToken.None); - } - - // Always start at the beginning. - request.Body.Seek(0L, SeekOrigin.Begin); - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/WebHookAttribute.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/WebHookAttribute.cs deleted file mode 100644 index e140208..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/WebHookAttribute.cs +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.AspNetCore.WebHooks.Filters; -using Microsoft.AspNetCore.WebHooks.Properties; -using Microsoft.Extensions.DependencyInjection; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Base for s indicating the associated action is a WebHook endpoint. Specifies the - /// required (in most cases) and optional . Also adds a - /// for the action. - /// - /// - /// - /// If the application enables CORS in general (see the Microsoft.AspNetCore.Cors package), apply - /// DisableCorsAttribute to this action. If the application depends on the - /// Microsoft.AspNetCore.Mvc.ViewFeatures package, apply IgnoreAntiforgeryTokenAttribute to this - /// action. - /// - /// - /// Subclasses of should be used at most once per and - /// in a WebHook application. Some subclasses support additional uniqueness constraints. - /// - /// - [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] - public abstract class WebHookAttribute : Attribute, IAllowAnonymous, IFilterFactory - { - private string _id; - - internal WebHookAttribute() - { - } - - /// - /// Instantiates a new indicating the associated action is a WebHook endpoint - /// for the given . - /// - /// The name of an available . - protected WebHookAttribute(string receiverName) - { - if (string.IsNullOrEmpty(receiverName)) - { - throw new ArgumentException(Resources.General_ArgumentCannotBeNullOrEmpty, nameof(receiverName)); - } - - ReceiverName = receiverName; - } - - /// - /// Gets the name of an available . - /// - public string ReceiverName { get; } - - /// - /// Gets or sets the id of the configuration this action accepts. - /// - /// - /// Default value is , indicating this action accepts all requests for this - /// . - /// - public string Id - { - get - { - return _id; - } - set - { - if (string.IsNullOrEmpty(value)) - { - throw new ArgumentException(Resources.General_ArgumentCannotBeNullOrEmpty, nameof(value)); - } - - _id = value; - } - } - - /// - /// - /// Allow the service's registration to determine its lifetime. - /// - bool IFilterFactory.IsReusable => false; - - /// - IFilterMetadata IFilterFactory.CreateInstance(IServiceProvider serviceProvider) - { - if (serviceProvider == null) - { - throw new ArgumentNullException(nameof(serviceProvider)); - } - - var filter = serviceProvider.GetRequiredService(); - return filter; - } - } -} diff --git a/src/Microsoft.AspNetCore.WebHooks.Receivers/WebHookConstants.cs b/src/Microsoft.AspNetCore.WebHooks.Receivers/WebHookConstants.cs deleted file mode 100644 index d80ea0e..0000000 --- a/src/Microsoft.AspNetCore.WebHooks.Receivers/WebHookConstants.cs +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.AspNetCore.WebHooks.Routing; -using Microsoft.Extensions.Configuration; - -namespace Microsoft.AspNetCore.WebHooks -{ - /// - /// Well-known names and values used in WebHook receivers and handlers. - /// - public static class WebHookConstants - { - /// - /// Gets the minimum length of the query parameter value and secret key - /// for receivers using such a query parameter. - /// - /// - public static int CodeParameterMinLength => 32; - - /// - /// Gets the maximum length of the query parameter value and secret key - /// for receivers using such a query parameter. - /// - /// - public static int CodeParameterMaxLength => 128; - - /// - /// Gets the name of a query parameter containing the secret key used to verify some WebHook receivers' - /// requests. - /// - /// - public static string CodeQueryParameterName => "code"; - - /// - /// Gets the relative key name of the configuration value or (in a few cases) - /// containing a receiver's default secret key(s). This value or section is - /// an immediate child of the section for a receiver. - /// - public static string DefaultIdConfigurationKey => "default"; - - /// - /// Gets the key of a configuration value indicating the - /// should not ensure a secure (HTTPS) - /// connection with the sender. Configuration value, if any, should parse as a . If that - /// parsed configuration value is , the HTTPS check is disabled. Otherwise i.e. if the - /// configuration value does not exist, cannot be parsed, or parses as , - /// performs the check. - /// - /// - /// All receiver configurations should include - /// calls. For example, - /// calls the method if the receiver implements - /// in its metadata service. - /// - public static string DisableHttpsCheckConfigurationKey { get; } = ConfigurationPath.Combine( - ReceiverConfigurationSectionKey, - "DisableHttpsCheck"); - - /// - /// Gets the model name for the root of body-bound objects. Places errors for data parameters in - /// consistent entries, separate from entries for (for - /// example) parameters bound to route values. - /// - public static string ModelStateBodyModelName => "$body"; - - /// - /// Gets the key of the containing all configuration values used in this - /// package. Immediate children include global configuration values and receiver-specific - /// s. - /// - public static string ReceiverConfigurationSectionKey => "WebHooks"; - - /// - /// Gets the relative key name of the containing secret keys. This section - /// is an immediate child of the receiver-specific . For most receivers, - /// immediate children of this section are id and secret key pairs. - /// - public static string SecretKeyConfigurationKeySectionKey => "SecretKey"; - - /// - /// Gets the name of the entry containing the event name - /// for the current request when there is a single event name. - /// - /// - /// - public static string EventKeyName => "event"; - - /// - /// Gets the name of the entry containing the receiver id - /// for the current request. - /// - public static string IdKeyName => "id"; - - /// - /// Gets the name of the entry containing the receiver - /// name for the current request. - /// - /// - public static string ReceiverKeyName => "webHookReceiver"; - - /// - /// Gets the name of the entry containing an indication - /// the successfully confirmed the request matched a configured - /// receiver. - /// - public static string ReceiverExistsKeyName => nameof(WebHookReceiverExistsConstraint); - } -} diff --git a/src/shared/Utilities/ObjectPathUtilities.cs b/src/shared/Utilities/ObjectPathUtilities.cs deleted file mode 100644 index de2821f..0000000 --- a/src/shared/Utilities/ObjectPathUtilities.cs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Linq; -using System.Xml.Linq; -using System.Xml.XPath; -using Microsoft.Extensions.Primitives; -using Newtonsoft.Json.Linq; - -namespace Microsoft.AspNetCore.WebHooks.Utilities -{ - /// - /// Utility methods for extracting from objects using JSON paths and XPaths. - /// - internal static class ObjectPathUtilities - { - /// - /// Gets the that match in the . - /// - /// The to search. - /// The JSON path to match. - /// - /// The that match in the . - /// - public static StringValues GetStringValues(JContainer json, string jsonPath) - { - var tokens = json.SelectTokens(jsonPath); - var count = tokens.Count(); - switch (count) - { - case 0: - return StringValues.Empty; - - case 1: - return new StringValues((string)tokens.First()); - - default: - var eventArray = new string[count]; - var i = 0; - foreach (var token in tokens) - { - eventArray[i++] = (string)token; - } - - return new StringValues(eventArray); - } - } - - /// - /// Gets the that match in the . - /// - /// The to search. - /// The XPath to match. - /// - /// The that match in the . - /// - public static StringValues GetStringValues(XElement xml, string xPath) - { - var elements = xml.XPathSelectElements(xPath); - var count = elements.Count(); - switch (count) - { - case 0: - return StringValues.Empty; - - case 1: - return new StringValues(elements.First().Value); - - default: - var eventArray = new string[count]; - var i = 0; - foreach (var element in elements) - { - eventArray[i++] = element.Value; - } - - return new StringValues(eventArray); - } - } - } -} diff --git a/src/shared/Utilities/TrimmingTokenizer.cs b/src/shared/Utilities/TrimmingTokenizer.cs deleted file mode 100644 index da7e436..0000000 --- a/src/shared/Utilities/TrimmingTokenizer.cs +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections; -using System.Collections.Generic; -using Microsoft.Extensions.Primitives; - -namespace Microsoft.AspNetCore.WebHooks.Utilities -{ - /// - /// Splits a or into trimmed s. Also - /// skips empty s. - /// - internal struct TrimmingTokenizer : IEnumerable - { - private readonly int _maxCount; - private readonly StringSegment _originalString; - private readonly StringTokenizer _tokenizer; - - /// - /// Instantiates a new with given . Will split segments - /// using given . - /// - /// The to split and trim. - /// The collection of separator s controlling the split. - public TrimmingTokenizer(string value, char[] separators) - : this(value, separators, maxCount: int.MaxValue) - { - } - - /// - /// Instantiates a new with given . Will split up to - /// segments using given . - /// - /// The to split and trim. - /// The collection of separator s controlling the split. - /// The maximum number of s to return. - public TrimmingTokenizer(string value, char[] separators, int maxCount) - : this(new StringSegment(value), separators, maxCount) - { - } - - /// - /// Instantiates a new with given . Will split segments - /// using given . - /// - /// The to split and trim. - /// The collection of separator s controlling the split. - public TrimmingTokenizer(StringSegment value, char[] separators) - : this(value, separators, maxCount: int.MaxValue) - { - } - - /// - /// Instantiates a new with given . Will split up to - /// segments using given . - /// - /// The to split and trim. - /// The collection of separator s controlling the split. - /// The maximum number of s to return. - public TrimmingTokenizer(StringSegment value, char[] separators, int maxCount) - { - // !HasValue matches odd-looking (for a struct) value==null check in StringTokenizer(...). - if (!value.HasValue) - { - throw new ArgumentNullException(nameof(value)); - } - if (separators == null) - { - throw new ArgumentNullException(nameof(separators)); - } - if (maxCount < 0) - { - throw new ArgumentOutOfRangeException(nameof(maxCount)); - } - - _maxCount = maxCount; - _originalString = value; - _tokenizer = new StringTokenizer(value, separators); - } - - /// - /// Gets the number of elements in this . - /// - /// - /// Provided to avoid either (or both) System.Linq use or boxing the . - /// - public int Count - { - get - { - var enumerator = GetEnumerator(); - var count = 0; - while (enumerator.MoveNext()) - { - count++; - } - - return count; - } - } - - /// - /// Returns an that iterates through the split and trimmed - /// s. - /// - /// - /// An that iterates through the split and trimmed s. - /// - public Enumerator GetEnumerator() => new Enumerator(this); - - /// - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - /// - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - /// - /// An wrapping and providing - /// trimmed s. - /// - public struct Enumerator : IEnumerator, IEnumerator, IDisposable - { - private readonly TrimmingTokenizer _tokenizer; - - private int _count; - private StringTokenizer.Enumerator _enumerator; - private StringSegment _remainder; - - /// - /// Instantiates a new instance for . - /// - /// The containing . - public Enumerator(TrimmingTokenizer tokenizer) - { - _tokenizer = tokenizer; - _count = 0; - _enumerator = tokenizer._tokenizer.GetEnumerator(); - _remainder = StringSegment.Empty; - } - - /// - public StringSegment Current - { - get - { - if (_count < _tokenizer._maxCount) - { - return _enumerator.Current.Trim(); - } - - return _remainder; - } - } - - /// - object IEnumerator.Current => Current; - - /// - public void Dispose() => _enumerator.Dispose(); - - /// - public bool MoveNext() - { - // Do nothing except return false if _maxCount == 0. - var result = false; - if (_count < _tokenizer._maxCount) - { - // Keep moving until enumeration is done or we find a non-empty (and non-whitespace) segment. - do - { - result = _enumerator.MoveNext(); - } - while (result && StringSegment.IsNullOrEmpty(Current)); - - if (result) - { - if (_count + 1 >= _tokenizer._maxCount) - { - _remainder = _tokenizer._originalString - .Subsegment(Current.Offset - _tokenizer._originalString.Offset) - .Trim(); - } - - _count++; - } - } - - return result; - } - - /// - public void Reset() - { - _count = 0; - _enumerator.Reset(); - _remainder = StringSegment.Empty; - } - } - } -} diff --git a/test/Directory.Build.props b/test/Directory.Build.props deleted file mode 100644 index 0bd0a98..0000000 --- a/test/Directory.Build.props +++ /dev/null @@ -1,15 +0,0 @@ - - - <_ImportParentFile>false - <_ImportParentFile Condition="$(MSBuildProjectName.StartsWith( 'Microsoft.AspNetCore.' ))">true - - - - - - $(DefineConstants);ASPNETWEBHOOKS - false - true - Microsoft.AspNetCore.WebHooks - - diff --git a/test/Microsoft.AspNetCore.WebHooks.Receivers.Slack.Test/Microsoft.AspNetCore.WebHooks.Receivers.Slack.Test.csproj b/test/Microsoft.AspNetCore.WebHooks.Receivers.Slack.Test/Microsoft.AspNetCore.WebHooks.Receivers.Slack.Test.csproj deleted file mode 100644 index ad698b7..0000000 --- a/test/Microsoft.AspNetCore.WebHooks.Receivers.Slack.Test/Microsoft.AspNetCore.WebHooks.Receivers.Slack.Test.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - $(Configurations);CodeAnalysis - netcoreapp2.0;net461 - - - - - - - - - - - diff --git a/test/Microsoft.AspNetCore.WebHooks.Receivers.Slack.Test/SlackCommandTests.cs b/test/Microsoft.AspNetCore.WebHooks.Receivers.Slack.Test/SlackCommandTests.cs deleted file mode 100644 index bda9d64..0000000 --- a/test/Microsoft.AspNetCore.WebHooks.Receivers.Slack.Test/SlackCommandTests.cs +++ /dev/null @@ -1,293 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using Microsoft.Extensions.Primitives; -using Xunit; - -namespace Microsoft.AspNetCore.WebHooks -{ - public class SlackCommandTests - { - public static TheoryData> ActionWithValueData - { - get - { - return new TheoryData> - { - { null, new KeyValuePair(string.Empty, string.Empty) }, - { string.Empty, new KeyValuePair(string.Empty, string.Empty) }, - { " ", new KeyValuePair(string.Empty, string.Empty) }, - { "你好", new KeyValuePair("你好", string.Empty) }, - { " 你好 ", new KeyValuePair("你好", string.Empty) }, - { "你好 世界", new KeyValuePair("你好", "世界") }, - { " 你好 世界 ", new KeyValuePair("你好", "世界") }, - { "你好 世界", new KeyValuePair("你好", "世界") }, - { "你好 世界", new KeyValuePair("你好", "世界") }, - { "你 好 世 界", new KeyValuePair("你", "好 世 界") }, - { "你 好;世\\界\\;", new KeyValuePair("你", "好;世\\界\\;") }, - { " 你 好;世\\界\\; ", new KeyValuePair("你", "好;世\\界\\;") }, - }; - } - } - - public static TheoryData RoundTripData - { - get - { - return new TheoryData - { - { null, string.Empty }, - { string.Empty, string.Empty }, - { "p1=v1", "p1=v1" }, - { " p1 = v1 ", "p1=v1" }, - { "p1=v1; p1=v2", "p1=v1; p1=v2" }, - { "p1=v1 ;p2=v2", "p1=v1; p2=v2" }, - { "p1=v'1 ;p2=v\"2", "p1=v'1; p2=v\"2" }, - { "p1=' v1'; p2=\" v2\"", "p1=' v1'; p2=' v2'" }, - { "p1='v1 '; p2=\"v2 \"", "p1='v1 '; p2='v2 '" }, - { "p1=v 1 ; p2=\"v 2\" ", "p1=v 1; p2=v 2" }, - { "p1=' v1 '; p2=\" v2 \"", "p1=' v1 '; p2=' v2 '" }, - { "p1=' v\"1 '; p2=\" v'2 \"", "p1=' v\"1 '; p2=\" v'2 \"" }, - { "p1='v;1'; p2=\"v;2\"", "p1=v\\;1; p2=v\\;2" }, - { "p1=\\;v1; p2=v\\;2; p3=v3\\;", "p1=\\;v1; p2=v\\;2; p3=v3\\;" }, - { "p1=\\;v1; p2=v\\;2; p1=v3\\;", "p1=\\;v1; p1=v3\\;; p2=v\\;2" }, - { " 世=界", "世=界" }, - - { "a=b;b=c", "a=b; b=c" }, - { "a=b; b=c", "a=b; b=c" }, - { "a= b ; b=c", "a=b; b=c" }, - - { "a;b", "a; b" }, - { "a; b", "a; b" }, - { "a=;b=", "a; b" }, - { "a = ; b = ", "a; b" }, - { "a='';b=''", "a; b" }, - { "a=\"\";b=\"\"", "a; b" }, - { "a= '';b=''", "a; b" }, - { "a= \"\" ; b=\"\"", "a; b" }, - - { "a='b';b='c'", "a=b; b=c" }, - { "a=\"b\";b=\"c\"", "a=b; b=c" }, - { "a=';b';b='c;'", "a=\\;b; b=c\\;" }, - { "a=\";b\";b=\"c;\"", "a=\\;b; b=c\\;" }, - - { "abcd", "abcd" }, - { "a=abcd", "a=abcd" }, - { "a='abcd'", "a=abcd" }, - { "a=\"abcd\"", "a=abcd" }, - { "a=ab\\;cd", "a=ab\\;cd" }, - { "a='ab;cd'", "a=ab\\;cd" }, - { "a=\"ab;cd\"", "a=ab\\;cd" }, - { "a='ab\\;cd'", "a=ab\\\\;cd" }, - { "a=\"ab\\;cd\"", "a=ab\\\\;cd" }, - - { "a=''", "a" }, - { "a=\"\"", "a" }, - { "a=\\;", "a=\\;" }, - { "a=';'", "a=\\;" }, - { "a=\";\"", "a=\\;" }, - - { "a=\\;\\;\\;\\;", "a=\\;\\;\\;\\;" }, - { "a=\\;\\;;b=\\;\\;", "a=\\;\\;; b=\\;\\;" }, - { "a=';;;;'", "a=\\;\\;\\;\\;" }, - { "a=\";;;;\"", "a=\\;\\;\\;\\;" }, - { "a=';;';b=';;'", "a=\\;\\;; b=\\;\\;" }, - { "a=\";;\";b=\";;\"", "a=\\;\\;; b=\\;\\;" }, - { "a='\\;\\;\\;\\;'", "a=\\\\;\\\\;\\\\;\\\\;" }, - { "a=\"\\;\\;\\;\\;\"", "a=\\\\;\\\\;\\\\;\\\\;" }, - { "a='\\;\\;';b='\\;\\;'", "a=\\\\;\\\\;; b=\\\\;\\\\;" }, - { "a=\"\\;\\;\";b=\"\\;\\;\"", "a=\\\\;\\\\;; b=\\\\;\\\\;" }, - }; - } - } - - [Theory] - [MemberData(nameof(ActionWithValueData))] - public void ParseActionWithValue_HandlesInput(string text, KeyValuePair expected) - { - // Arrange & Act - var actual = SlackCommand.ParseActionWithValue(text); - - // Assert - Assert.Equal(expected, actual); - } - - [Theory] - [InlineData("text")] - [InlineData(" text")] - [InlineData("\\text")] - [InlineData(" text\\")] - [InlineData(" text\\ text ")] - [InlineData("你 世界")] - [InlineData(" 你 世界 ")] - public void ParseParameters_AcceptsValidName(string name) - { - // Arrange & Act - var expectedName = name.Trim(); - var (result, error) = SlackCommand.ParseParameters(name); - - // Assert - var keyValuePair = Assert.Single(result); - Assert.True(keyValuePair.Key.HasValue); - Assert.Equal(expectedName, keyValuePair.Key.Value); - - var segment = Assert.Single(keyValuePair.Value); - Assert.True(StringSegment.IsNullOrEmpty(segment)); - - Assert.Null(error); - } - - [Theory] - [InlineData("text", "text")] - [InlineData(" text", "text")] - [InlineData("你 世界", "你 世界")] - [InlineData(" 你 世界 ", "你 世界")] - [InlineData("'text'", "text")] - [InlineData(" 'text'", "text")] - [InlineData(" ' text'", " text")] - [InlineData(" 'text '", "text ")] - [InlineData(" ' text '", " text ")] - [InlineData("'你 世界'", "你 世界")] - [InlineData(" '你 世界 '", "你 世界 ")] - [InlineData("\"text\"", "text")] - [InlineData(" \"text\"", "text")] - [InlineData(" \" text\"", " text")] - [InlineData(" \"text \"", "text ")] - [InlineData(" \" text \"", " text ")] - [InlineData("\"你 世界\"", "你 世界")] - [InlineData(" \"你 世界 \"", "你 世界 ")] - [InlineData("text'text", "text'text")] - [InlineData("text \" text", "text \" text")] - [InlineData(" text \" text ", "text \" text")] - [InlineData("\\", "\\")] - [InlineData("\\;", ";")] - [InlineData("\\\\;", "\\;")] - [InlineData("\\;\\", ";\\")] - [InlineData(" \\; ", ";")] - [InlineData("';'", ";")] - [InlineData(" ';;' ", ";;")] - [InlineData("' ;;; '", " ;;; ")] - [InlineData("' ;\"; '", " ;\"; ")] - [InlineData("\";\"", ";")] - [InlineData(" \";;\" ", ";;")] - [InlineData("\" ;;; \"", " ;;; ")] - [InlineData("\" ;'; \"", " ;'; ")] - public void ParseParameters_AcceptsValidValue(string value, string expectedValue) - { - // Arrange & Act - var (result, error) = SlackCommand.ParseParameters($"name={value}"); - - // Assert - var keyValuePair = Assert.Single(result); - Assert.True(keyValuePair.Key.HasValue); - Assert.Equal("name", keyValuePair.Key.Value); - - var segment = Assert.Single(keyValuePair.Value); - Assert.True(segment.HasValue); - Assert.Equal(expectedValue, segment.Value); - - Assert.Null(error); - } - - [Theory] - [MemberData(nameof(RoundTripData))] - public void ParseParameters_GetNormalizedParameterString_RoundTrips(string text, string expectedParameters) - { - // Arrange & Act - var (result, error) = SlackCommand.ParseParameters(text); - var actual = SlackCommand.GetNormalizedParameterString(result); - - // Assert - Assert.Null(error); - Assert.Equal(expectedParameters, actual); - } - - [Theory] - [InlineData("'text'", '\'', 0)] - [InlineData("\"text\"", '"', 0)] - [InlineData(" \"text\"", '"', 3)] - public void ParseParameters_ReturnsError_IfQuotedName(string name, char quote, int offset) - { - // Arrange - var expected = $"Parameter name cannot be a quoted string. Unexpected character ({quote}) " + - $"discovered at position {offset}."; - - // Act - var (result, error) = SlackCommand.ParseParameters(name); - - // Assert - Assert.Null(result); - Assert.StartsWith(expected, error); - } - - [Theory] - [InlineData("\\;text", 0)] - [InlineData("te\\;xt", 2)] - [InlineData("te\\;\\;xt", 2)] - [InlineData("text\\;", 4)] - [InlineData(" \\;text ", 2)] - [InlineData(" te\\;xt", 4)] - [InlineData(" text\\; ", 6)] - public void ParseParameters_ReturnsError_IfInvalidName(string name, int offset) - { - // Arrange - var expected = "Parameter name cannot contain ';' characters. Unexpected escape sequence (\\;) " + - $"discovered at position {offset}."; - - // Act - var (result, error) = SlackCommand.ParseParameters(name); - - // Assert - Assert.Null(result); - Assert.Equal(expected, error); - } - - [Theory] - [InlineData("a='", '\'', 2 )] - [InlineData("a=\"", '"', 2 )] - [InlineData(" a=\"", '"', 4)] - [InlineData("a='b;b=c", '\'', 2)] - [InlineData(" a='b; b=c", '\'', 4)] - [InlineData("a=\"b;b=c", '"', 2)] - [InlineData("a='b;b=\"c\"", '\'', 2)] - [InlineData("a=\"b;b='c'", '"', 2)] - [InlineData(" a=\"b; b='c' ", '"', 5)] - public void ParseParameters_ReturnsError_IfValueContainsMismatchedQuote(string input, char quote, int offset) - { - // Arrange - var expected = $"Unmatched quote ({quote}) discovered at position {offset}."; - - // Act - var (result, error) = SlackCommand.ParseParameters(input); - - // Assert - Assert.Null(result); - Assert.Equal(expected, error); - } - - [Theory] - [InlineData("a='''", '\'', 4)] - [InlineData("a=\"\"\"", '"', 4)] - [InlineData(" a=\"\"\"", '"', 6)] - [InlineData("a='b;b='c'", 'c', 8)] - [InlineData(" a='b;b=' c'", 'c', 12)] - [InlineData("a=\"b;b=\"c\"", 'c', 8)] - [InlineData("a=';b;b='c;'", 'c', 9)] - [InlineData("a=\";b;b=\"c;\"", 'c', 9)] - [InlineData(" a=\";b;b=\" c; \"", 'c', 12)] - public void ParseParameters_ReturnsError_IfTextFoundAfterQuotedString(string input, char ch, int offset) - { - // Arrange - var expected = $"Parameter value contains text after a quoted string. Unexpected character ({ch}) " + - $"discovered at position {offset}."; - - // Act - var (result, error) = SlackCommand.ParseParameters(input); - - // Assert - Assert.Null(result); - Assert.Equal(expected, error); - } - } -} diff --git a/test/Microsoft.AspNetCore.WebHooks.Receivers.Stripe.Test/Filters/StripeVerifySignatureFilterTests.cs b/test/Microsoft.AspNetCore.WebHooks.Receivers.Stripe.Test/Filters/StripeVerifySignatureFilterTests.cs deleted file mode 100644 index cb42134..0000000 --- a/test/Microsoft.AspNetCore.WebHooks.Receivers.Stripe.Test/Filters/StripeVerifySignatureFilterTests.cs +++ /dev/null @@ -1,542 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Security.Cryptography; -using System.Text; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Abstractions; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.AspNetCore.Mvc.ModelBinding; -using Microsoft.AspNetCore.Routing; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging.Abstractions; -using Moq; -using Xunit; - -namespace Microsoft.AspNetCore.WebHooks.Filters -{ - public class StripeVerifySignatureFilterTests - { - private const string ExtraHeaderContent = - " v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd, " + - "v0=6ffbb59b2300aae63f272406069a9788598b792a944a07aba816edb039989a39 "; - private const string TestContent = "{ \"type\": \"action\", \"id\": \"" + TestStripeId + "\" }"; - private const string TestId = ""; - private const string TestSecret = "12345678901234567890123456789012"; - private const string TestStripeId = "12345"; - private const string TestTimestamp = "1492774577"; - - private static readonly string TestSignatureHeader = GetSignatureHeader(TestContent); - - public static TheoryData HeadersWithMissingValues - { - get - { - return new TheoryData - { - string.Empty, - $"{StripeConstants.TimestampKey}={TestTimestamp} ", - ExtraHeaderContent, - "a=b, b=c, c=d, e=f", - }; - } - } - - public static TheoryData InvalidReceiverData - { - get - { - return new TheoryData - { - { string.Empty }, - { "你好" }, - { "1" }, - { "1234567890" }, - { "github" }, - }; - } - } - - public static TheoryData ValidIdData - { - get - { - return new TheoryData - { - { string.Empty }, - { "id" }, - { "你好" }, - { "1" }, - { "1234567890" }, - }; - } - } - - [Fact] - public void ReceiverName_IsConsistent() - { - // Arrange - var filter = GetFilter(); - var expected = "stripe"; - - // Act - var actual = filter.ReceiverName; - - // Assert - Assert.Equal(expected, actual); - } - - [Theory] - [MemberData(nameof(InvalidReceiverData))] - public void IsApplicable_ReturnsFalseForNonMatches(string receiverName) - { - // Arrange - var filter = GetFilter(); - - // Act - var actual = filter.IsApplicable(receiverName); - - // Assert - Assert.False(actual); - } - - [Theory] - [InlineData("stripe")] - [InlineData("Stripe")] - [InlineData("STRIPE")] - public void IsApplicable_ReturnsTrueForMatches(string receiverName) - { - // Arrange - var filter = GetFilter(); - - // Act - var actual = filter.IsApplicable(receiverName); - - // Assert - Assert.True(actual); - } - - [Fact] - public async Task OnResourceExecutionAsync_Fails_IfPostHasNoSignatureHeader() - { - // Arrange - var expectedMessage = $"Expecting exactly one '{StripeConstants.SignatureHeaderName}' header field in " + - "the WebHook request but found 0. Please ensure the request contains exactly one " + - $"'{StripeConstants.SignatureHeaderName}' header field."; - var filter = GetFilter(TestSecret); - var context = GetContext(TestContent); - - // Act - await filter.OnResourceExecutionAsync(context, () => throw new InvalidOperationException("Unreachable")); - - // Assert - var result = Assert.IsType(context.Result); - Assert.Equal(400, result.StatusCode); - Assert.Equal(expectedMessage, result.Value); - } - - [Fact] - public async Task OnResourceExecutionAsync_Fails_IfPostHasTwoSignatureHeaders() - { - // Arrange - var expectedMessage = $"Expecting exactly one '{StripeConstants.SignatureHeaderName}' header field in " + - "the WebHook request but found 2. Please ensure the request contains exactly one " + - $"'{StripeConstants.SignatureHeaderName}' header field."; - var filter = GetFilter(TestSecret); - var context = GetContext(TestContent); - context.HttpContext.Request.Headers.Add(StripeConstants.SignatureHeaderName, "value1"); - context.HttpContext.Request.Headers.Append(StripeConstants.SignatureHeaderName, "value2"); - - // Act - await filter.OnResourceExecutionAsync(context, () => throw new InvalidOperationException("Unreachable")); - - // Assert - var result = Assert.IsType(context.Result); - Assert.Equal(400, result.StatusCode); - Assert.Equal(expectedMessage, result.Value); - } - - [Theory] - [InlineData("你好世界")] - [InlineData("invalid")] - [InlineData("==")] - [InlineData(",=,=,")] - public async Task OnResourceExecutionAsync_Fails_IfPostHasInvalidSignatureHeader(string header) - { - // Arrange - var expectedMessage = $"The '{StripeConstants.SignatureHeaderName}' header value is invalid. It must be " + - "formatted as key=value pairs separated by commas."; - var filter = GetFilter(TestSecret); - var context = GetContext(TestContent); - context.HttpContext.Request.Headers.Add(StripeConstants.SignatureHeaderName, header); - - // Act - await filter.OnResourceExecutionAsync(context, () => throw new InvalidOperationException("Unreachable")); - - // Assert - var result = Assert.IsType(context.Result); - Assert.Equal(400, result.StatusCode); - Assert.Equal(expectedMessage, result.Value); - } - - [Theory] - [MemberData(nameof(HeadersWithMissingValues))] - public async Task OnResourceExecutionAsync_Fails_IfPostHasSignatureHeaderWithMissingValues(string header) - { - // Arrange - var expectedMessage = $"The '{StripeConstants.SignatureHeaderName}' header value is invalid. It " + - $"must contain timestamp ('{StripeConstants.TimestampKey}') and signature " + - $"('{StripeConstants.SignatureKey}') values."; - var filter = GetFilter(TestSecret); - var context = GetContext(TestContent); - context.HttpContext.Request.Headers.Add(StripeConstants.SignatureHeaderName, header); - - // Act - await filter.OnResourceExecutionAsync(context, () => throw new InvalidOperationException("Unreachable")); - - // Assert - var result = Assert.IsType(context.Result); - Assert.Equal(400, result.StatusCode); - Assert.Equal(expectedMessage, result.Value); - } - - [Fact] - public async Task OnResourceExecutionAsync_Fails_IfPostHasInvalidSignatureEncoding() - { - // Arrange - var expectedMessage = $"The '{StripeConstants.SignatureHeaderName}' header value is invalid. It must be " + - "a valid hex-encoded string."; - var filter = GetFilter(TestSecret); - var context = GetContext(TestContent); - var header = $"{StripeConstants.TimestampKey}={TestTimestamp}, " + - $"{StripeConstants.SignatureKey}=invalid"; - context.HttpContext.Request.Headers.Add(StripeConstants.SignatureHeaderName, header); - - // Act - await filter.OnResourceExecutionAsync(context, () => throw new InvalidOperationException("Unreachable")); - - // Assert - var result = Assert.IsType(context.Result); - Assert.Equal(400, result.StatusCode); - Assert.Equal(expectedMessage, result.Value); - } - - [Fact] - public async Task OnResourceExecutionAsync_Fails_IfPostHasIncorrectSignature() - { - // Arrange - var expectedMessage = $"The signature provided by the '{StripeConstants.SignatureHeaderName}' header " + - $"field does not match the value expected by the '{StripeConstants.ReceiverName}' WebHook receiver. " + - "WebHook request is invalid."; - var filter = GetFilter(TestSecret); - var context = GetContext(TestContent); - var header = $"{StripeConstants.TimestampKey}={TestTimestamp}, {ExtraHeaderContent}"; - context.HttpContext.Request.Headers.Add(StripeConstants.SignatureHeaderName, header); - - // Act - await filter.OnResourceExecutionAsync(context, () => throw new InvalidOperationException("Unreachable")); - - // Assert - var result = Assert.IsType(context.Result); - Assert.Equal(400, result.StatusCode); - Assert.Equal(expectedMessage, result.Value); - } - - [Fact] - public async Task OnResourceExecutionAsync_Succeeds_IfPostIsNotJson() - { - // Arrange - var filter = GetFilter(TestSecret); - var context = GetContext(TestContent); - context.HttpContext.Request.ContentType = "application/x-www-form-urlencoded"; - context.HttpContext.Request.Headers.Add(StripeConstants.SignatureHeaderName, TestSignatureHeader); - var nextCount = 0; - - // Act - await filter.OnResourceExecutionAsync(context, () => - { - nextCount++; - var executedContext = new ResourceExecutedContext(context, context.Filters) - { - Result = context.Result, - }; - - return Task.FromResult(executedContext); - }); - - // Assert - Assert.Null(context.Result); - Assert.Equal(1, nextCount); - } - - [Fact] - public async Task OnResourceExecutionAsync_Succeeds_IfTestId() - { - // Arrange - var filter = GetFilter(TestSecret); - var content = "{ \"type\": \"action\", \"id\": \"" + StripeConstants.TestNotificationId + "\" }"; - var context = GetContext(content); - context.HttpContext.Request.Headers.Add(StripeConstants.SignatureHeaderName, GetSignatureHeader(content)); - var nextCount = 0; - - // Act - await filter.OnResourceExecutionAsync(context, () => - { - nextCount++; - var executedContext = new ResourceExecutedContext(context, context.Filters) - { - Result = context.Result, - }; - - return Task.FromResult(executedContext); - }); - - // Assert - Assert.Null(context.Result); - Assert.Equal(1, nextCount); - } - - [Fact] - public async Task OnResourceExecutionAsync_Succeeds_IfTestIdAndTestMode() - { - // Arrange - var settings = new Dictionary - { - { "WebHooks:Stripe:SecretKey:default", TestSecret }, - { StripeConstants.PassThroughTestEventsConfigurationKey, "true" }, - }; - - var filter = GetFilter(settings); - var content = "{ \"type\": \"action\", \"id\": \"" + StripeConstants.TestNotificationId + "\" }"; - var context = GetContext(content); - context.HttpContext.Request.Headers.Add(StripeConstants.SignatureHeaderName, GetSignatureHeader(content)); - var nextCount = 0; - - // Act - await filter.OnResourceExecutionAsync(context, () => - { - nextCount++; - var executedContext = new ResourceExecutedContext(context, context.Filters) - { - Result = context.Result, - }; - - return Task.FromResult(executedContext); - }); - - // Assert - Assert.Null(context.Result); - Assert.Equal(1, nextCount); - } - - [Theory] - [MemberData(nameof(ValidIdData))] - public async Task OnResourceExecutionAsync_Succeeds_IfValidPostRequest(string id) - { - // Arrange - var configurationId = string.IsNullOrEmpty(id) ? "default" : id; - var settings = new Dictionary - { - { $"WebHooks:Stripe:SecretKey:{configurationId}", TestSecret }, - }; - - var filter = GetFilter(settings); - var context = GetContext(TestContent); - context.HttpContext.Request.Headers.Add(StripeConstants.SignatureHeaderName, TestSignatureHeader); - context.RouteData.Values.Add(WebHookConstants.IdKeyName, id); - var nextCount = 0; - - // Act - await filter.OnResourceExecutionAsync(context, () => - { - nextCount++; - var executedContext = new ResourceExecutedContext(context, context.Filters) - { - Result = context.Result, - }; - - return Task.FromResult(executedContext); - }); - - // Assert - Assert.Null(context.Result); - Assert.Equal(1, nextCount); - } - - [Fact] - public async Task OnResourceExecutionAsync_Succeeds_IfValidPostRequest_WithExtraSignatureHeaderContent() - { - // Arrange - var filter = GetFilter(TestSecret); - var context = GetContext(TestContent); - var header = $" {TestSignatureHeader} , {ExtraHeaderContent} "; - context.HttpContext.Request.Headers.Add(StripeConstants.SignatureHeaderName, header); - var nextCount = 0; - - // Act - await filter.OnResourceExecutionAsync(context, () => - { - nextCount++; - var executedContext = new ResourceExecutedContext(context, context.Filters) - { - Result = context.Result, - }; - - return Task.FromResult(executedContext); - }); - - // Assert - Assert.Null(context.Result); - Assert.Equal(1, nextCount); - } - - [Fact] - public async Task OnResourceExecutionAsync_Succeeds_IfNoReceiverName() - { - // Arrange - var filter = GetFilter(TestSecret); - var context = GetContext(TestContent); - context.HttpContext.Request.Headers.Add(StripeConstants.SignatureHeaderName, TestSignatureHeader); - context.RouteData.Values.Remove(WebHookConstants.ReceiverKeyName); - var nextCount = 0; - - // Act - await filter.OnResourceExecutionAsync(context, () => - { - nextCount++; - var executedContext = new ResourceExecutedContext(context, context.Filters) - { - Result = context.Result, - }; - - return Task.FromResult(executedContext); - }); - - // Assert - Assert.Null(context.Result); - Assert.Equal(1, nextCount); - } - - [Theory] - [MemberData(nameof(InvalidReceiverData))] - public async Task OnResourceExecutionAsync_Succeeds_IfNotApplicable(string receiverName) - { - // Arrange - var filter = GetFilter(TestSecret); - var context = GetContext(TestContent); - context.HttpContext.Request.Headers.Add(StripeConstants.SignatureHeaderName, TestSignatureHeader); - context.RouteData.Values[WebHookConstants.ReceiverKeyName] = receiverName; - var nextCount = 0; - - // Act - await filter.OnResourceExecutionAsync(context, () => - { - nextCount++; - var executedContext = new ResourceExecutedContext(context, context.Filters) - { - Result = context.Result, - }; - - return Task.FromResult(executedContext); - }); - - // Assert - Assert.Null(context.Result); - Assert.Equal(1, nextCount); - } - - [Theory] - [InlineData("GET")] - [InlineData("HEAD")] - [InlineData("PATCH")] - [InlineData("PUT")] - [InlineData("OPTIONS")] - public async Task OnResourceExecutionAsync_Fails_IfInvalidMethod(string method) - { - // Arrange - var filter = GetFilter(TestSecret); - var context = GetContext(TestContent); - context.HttpContext.Request.Headers.Add(StripeConstants.SignatureHeaderName, TestSignatureHeader); - context.HttpContext.Request.Method = method; - var nextCount = 0; - - // Act - await filter.OnResourceExecutionAsync(context, () => - { - nextCount++; - var executedContext = new ResourceExecutedContext(context, context.Filters) - { - Result = context.Result, - }; - - return Task.FromResult(executedContext); - }); - - // Assert - Assert.Null(context.Result); - Assert.Equal(1, nextCount); - } - - private static ResourceExecutingContext GetContext(string content) - { - var httpContext = new DefaultHttpContext(); - httpContext.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(content)); - httpContext.Request.ContentType = "application/json"; - httpContext.Request.IsHttps = true; - httpContext.Request.Method = HttpMethods.Post; - - var routeData = new RouteData(); - routeData.Values.Add(WebHookConstants.ReceiverKeyName, StripeConstants.ReceiverName); - - return new ResourceExecutingContext( - new ActionContext(httpContext, routeData, new ActionDescriptor()), - new List(), - new List()); - } - - private static StripeVerifySignatureFilter GetFilter(IDictionary settings = null) - { - var builder = new ConfigurationBuilder(); - if (settings != null) - { - builder.AddInMemoryCollection(settings); - } - - return new StripeVerifySignatureFilter( - builder.Build(), - Mock.Of(), - NullLoggerFactory.Instance); - } - - private static StripeVerifySignatureFilter GetFilter(string secretKey) - { - var settings = new Dictionary - { - { "WebHooks:Stripe:SecretKey:default", secretKey }, - }; - - return GetFilter(settings); - } - - private static string GetSignatureHeader(string content) - { - var secret = Encoding.UTF8.GetBytes(TestSecret); - using (var hasher = new HMACSHA256(secret)) - { - var fullContent = $"{TestTimestamp}.{content}"; - var data = Encoding.UTF8.GetBytes(fullContent); - var testHash = hasher.ComputeHash(data); - var signature = BitConverter.ToString(testHash).Replace("-", string.Empty); - - return $" {StripeConstants.TimestampKey}={TestTimestamp}, " + - $"{StripeConstants.SignatureKey}={signature} "; - } - } - } -} diff --git a/test/Microsoft.AspNetCore.WebHooks.Receivers.Stripe.Test/Microsoft.AspNetCore.WebHooks.Receivers.Stripe.Test.csproj b/test/Microsoft.AspNetCore.WebHooks.Receivers.Stripe.Test/Microsoft.AspNetCore.WebHooks.Receivers.Stripe.Test.csproj deleted file mode 100644 index 837c655..0000000 --- a/test/Microsoft.AspNetCore.WebHooks.Receivers.Stripe.Test/Microsoft.AspNetCore.WebHooks.Receivers.Stripe.Test.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - $(Configurations);CodeAnalysis - netcoreapp2.0;net461 - - - - - - - - - - - - diff --git a/test/Microsoft.AspNetCore.WebHooks.Receivers.Stripe.Test/ModelBinding/UnixTimeConverterTests.cs b/test/Microsoft.AspNetCore.WebHooks.Receivers.Stripe.Test/ModelBinding/UnixTimeConverterTests.cs deleted file mode 100644 index a2db0de..0000000 --- a/test/Microsoft.AspNetCore.WebHooks.Receivers.Stripe.Test/ModelBinding/UnixTimeConverterTests.cs +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Newtonsoft.Json; -using Xunit; - -namespace Microsoft.AspNetCore.WebHooks.ModelBinding -{ - public class UnixTimeConverterTests - { - private static readonly DateTime _Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); - - public static TheoryData NullDateTimeValues - { - get - { - return new TheoryData - { - "{ \"Value\": null }", - "{ \"Value\": { } }", - "{ \"Value\": [ ] }", - }; - } - } - - public static TheoryData InvalidDateTimeValues - { - get - { - return new TheoryData - { - "{ \"Value\": \"invalid\" }", - "{ \"Value\": 1.23456 }", - "{ \"Value\": true }", - }; - } - } - - public static TheoryData ValidReadDateTimeValues - { - get - { - return new TheoryData - { - 0, - 1442710070, - -144271007, - int.MinValue, - int.MaxValue, - }; - } - } - - public static TheoryData ValidWriteDateTimeValues - { - get - { - return new TheoryData - { - { new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc), "{\"Value\":0}" }, - { new DateTime(1960, 1, 1, 0, 0, 0, DateTimeKind.Utc), "{\"Value\":-315619200}" }, - { new DateTime(2015, 1, 1, 0, 0, 0, DateTimeKind.Utc), "{\"Value\":1420070400}" } - }; - } - } - - public static TheoryData RoundtripValues - { - get - { - return new TheoryData - { - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc), - new DateTime(1960, 1, 1, 0, 0, 0, DateTimeKind.Utc), - new DateTime(2015, 1, 1, 0, 0, 0, DateTimeKind.Utc), - }; - } - } - - [Theory] - [MemberData(nameof(NullDateTimeValues))] - public void ReadJson_ThrowsOnNull(string input) - { - // Act - var ex = Assert.Throws(() => JsonConvert.DeserializeObject(input)); - - // Assert - Assert.Equal("Cannot convert null value to type 'DateTime'.", ex.Message); - } - - [Theory] - [MemberData(nameof(InvalidDateTimeValues))] - public void ReadJson_ThrowsOnInvalidValue(string input) - { - // Act - var ex = Assert.Throws(() => JsonConvert.DeserializeObject(input)); - - // Assert - Assert.StartsWith("Cannot read value '", ex.Message); - } - - [Theory] - [MemberData(nameof(ValidReadDateTimeValues))] - public void ReadJson_ReadsValue_AsUtc(long delta) - { - // Arrange - var expected = _Epoch.AddSeconds(delta); - var input = string.Format("{{ \"Value\": \"{0}\" }}", delta); - - // Act - var actual = JsonConvert.DeserializeObject(input); - var utcActual = actual.Value.ToUniversalTime(); - - // Assert - Assert.Equal(expected, actual.Value); - Assert.Equal(expected, utcActual); - } - - [Theory] - [MemberData(nameof(ValidWriteDateTimeValues))] - public void WriteJson_WritesValue_AsUtc(DateTime input, string expected) - { - // Arrange - var data = new TestClass() { Value = input }; - - // Act - var actual = JsonConvert.SerializeObject(data); - - // Assert - Assert.Equal(expected, actual); - } - - [Theory] - [MemberData(nameof(RoundtripValues))] - public void WriteJson_ReadJson_Roundtrips(DateTime expected) - { - // Arrange - var data = new TestClass() { Value = expected }; - - // Act - var serialized = JsonConvert.SerializeObject(data); - var actualData = JsonConvert.DeserializeObject(serialized); - var actual = actualData.Value; - - // Assert - Assert.Equal(expected, actual); - } - - private class TestClass - { - [JsonConverter(typeof(UnixTimeConverter))] - public DateTime Value { get; set; } - } - } -} diff --git a/test/Microsoft.AspNetCore.shared.Test/Internal/TrimmingTokenizerTests.cs b/test/Microsoft.AspNetCore.shared.Test/Internal/TrimmingTokenizerTests.cs deleted file mode 100644 index 93ab2d3..0000000 --- a/test/Microsoft.AspNetCore.shared.Test/Internal/TrimmingTokenizerTests.cs +++ /dev/null @@ -1,272 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Linq; -using Microsoft.Extensions.Primitives; -using Xunit; - -namespace Microsoft.AspNetCore.WebHooks.Utilities -{ - public class TrimmingTokenizerTests - { - public static TheoryData CountData - { - get - { - return new TheoryData - { - { string.Empty, new[] { ',' }, 0 }, - { " ", new[] { ',' }, 0 }, - { ",,,", new[] { ',' }, 0 }, - { " , , , ", new[] { ',' }, 0 }, - { "a,b,c", Array.Empty(), 1 }, - { "a, b, c", Array.Empty(), 1 }, - { ",,,a, ,,,b, c,,,", Array.Empty(), 1 }, - { " , , , a, , , , b, c, , , ", Array.Empty(), 1 }, - { " , , , a, , , , b, c, , , ", new[] { ' ' }, 11 }, - { "a,b,c", new[] { ',' }, 3 }, - { " a , b , c ", new[] { ',' }, 3 }, - { ",,,a, ,,,b, c,,,", new[] { ',' }, 3 }, - { " , , , a, , , , b, c, , , ", new[] { ',' }, 3 }, - { ",;,a, ,;,b, c,;,", new[] { ',', ';' }, 3 }, - { " , ; , a, ; , , b, c, ; , ", new[] { ',', ';' }, 3 }, - { ";,;a; ;,;b; c;,;", new[] { ',', ';' }, 3 }, - { " ; , ; a; , ; ; b; c; , ; ", new[] { ',', ';' }, 3 }, - { "a, b, c", new[] { '_' }, 1 }, - { "你,,好,, 世, ,\t,\r\n , 界", new[] { ',' }, 4 }, - }; - } - } - - public static TheoryData CountMax2Data - { - get - { - return new TheoryData - { - { string.Empty, new[] { ',' }, 0 }, - { " ", new[] { ',' }, 0 }, - { ",,,", new[] { ',' }, 0 }, - { " , , , ", new[] { ',' }, 0 }, - { "a,b,c", Array.Empty(), 1 }, - { "a, b, c", Array.Empty(), 1 }, - { ",,,a, ,,,b, c,,,", Array.Empty(), 1 }, - { " , , , a, , , , b, c, , , ", Array.Empty(), 1 }, - { " , , , a, , , , b, c, , , ", new[] { ' ' }, 2 }, - { "a,b,c", new[] { ',' }, 2 }, - { " a , b , c ", new[] { ',' }, 2 }, - { ",,,a, ,,,b, c,,,", new[] { ',' }, 2 }, - { " , , , a, , , , b, c, , , ", new[] { ',' }, 2 }, - { ",;,a, ,;,b, c,;,", new[] { ',', ';' }, 2 }, - { " , ; , a, ; , , b, c, ; , ", new[] { ',', ';' }, 2 }, - { ";,;a; ;,;b; c;,;", new[] { ',', ';' }, 2 }, - { " ; , ; a; , ; ; b; c; , ; ", new[] { ',', ';' }, 2 }, - { "a, b, c", new[] { '_' }, 1 }, - { "你,,好,, 世, ,\t,\r\n , 界", new[] { ',' }, 2 }, - }; - } - } - - public static TheoryData EnumeratorData - { - get - { - return new TheoryData - { - { string.Empty, new[] { ',' }, Array.Empty() }, - { " ", new[] { ',' }, Array.Empty() }, - { ",,,", new[] { ',' }, Array.Empty() }, - { " , , , ", new[] { ',' }, Array.Empty() }, - { "a,b,c", Array.Empty(), new StringSegment[] { "a,b,c" } }, - { "a, b, c", Array.Empty(), new StringSegment[] { "a, b, c" } }, - { ",,,a, ,,,b, c,,,", Array.Empty(), new StringSegment[] { ",,,a, ,,,b, c,,," } }, - { - " , , , a, , , , b, c, , , ", - Array.Empty(), - new StringSegment[] { ", , , a, , , , b, c, , ," } - }, - { - " , , , a, , , , b, c, , , ", - new[] { ' ' }, - new StringSegment[] { ",", ",", ",", "a,", ",", ",", ",", "b,", "c,", ",", "," } - }, - { "a,b,c", new[] { ',' }, new StringSegment[] { "a", "b", "c" } }, - { " a , b , c ", new[] { ',' }, new StringSegment[] { "a", "b", "c" } }, - { ",,,a, ,,,b, c,,,", new[] { ',' }, new StringSegment[] { "a", "b", "c" } }, - { " , , , a, , , , b, c, , , ", new[] { ',' }, new StringSegment[] { "a", "b", "c" } }, - { ",;,a, ,;,b, c,;,", new[] { ',', ';' }, new StringSegment[] { "a", "b", "c" } }, - { " , ; , a, ; , , b, c, ; , ", new[] { ',', ';' }, new StringSegment[] { "a", "b", "c" } }, - { ";,;a; ;,;b; c;,;", new[] { ',', ';' }, new StringSegment[] { "a", "b", "c" } }, - { " ; , ; a; , ; ; b; c; , ; ", new[] { ',', ';' }, new StringSegment[] { "a", "b", "c" } }, - { "a, b, c", new[] { '_' }, new StringSegment[] { "a, b, c" } }, - { "你,,好,, 世, ,\t,\r\n , 界", new[] { ',' }, new StringSegment[] { "你", "好", "世", "界" } }, - }; - } - } - - public static TheoryData EnumeratorMax2Data - { - get - { - return new TheoryData - { - { string.Empty, new[] { ',' }, Array.Empty() }, - { " ", new[] { ',' }, Array.Empty() }, - { ",,,", new[] { ',' }, Array.Empty() }, - { " , , , ", new[] { ',' }, Array.Empty() }, - { "a,b,c", Array.Empty(), new StringSegment[] { "a,b,c" } }, - { "a, b, c", Array.Empty(), new StringSegment[] { "a, b, c" } }, - { ",,,a, ,,,b, c,,,", Array.Empty(), new StringSegment[] { ",,,a, ,,,b, c,,," } }, - { - " , , , a, , , , b, c, , , ", - Array.Empty(), - new StringSegment[] { ", , , a, , , , b, c, , ," } - }, - { - " , , , a, , , , b, c, , , ", - new[] { ' ' }, - new StringSegment[] { ",", ", , a, , , , b, c, , ," } - }, - { "a,b,c", new[] { ',' }, new StringSegment[] { "a", "b,c" } }, - { " a , b , c ", new[] { ',' }, new StringSegment[] { "a", "b , c" } }, - { ",,,a, ,,,b, c,,,", new[] { ',' }, new StringSegment[] { "a", "b, c,,," } }, - { " , , , a, , , , b, c, , , ", new[] { ',' }, new StringSegment[] { "a", "b, c, , ," } }, - { ",;,a, ,;,b, c,;,", new[] { ',', ';' }, new StringSegment[] { "a", "b, c,;," } }, - { " , ; , a, ; , , b, c, ; , ", new[] { ',', ';' }, new StringSegment[] { "a", "b, c, ; ," } }, - { ";,;a; ;,;b; c;,;", new[] { ',', ';' }, new StringSegment[] { "a", "b; c;,;" } }, - { " ; , ; a; , ; ; b; c; , ; ", new[] { ',', ';' }, new StringSegment[] { "a", "b; c; , ;" } }, - { "a, b, c", new[] { '_' }, new StringSegment[] { "a, b, c" } }, - { - "你,,好,, 世, ,\t,\r\n , 界", - new[] { ',' }, - new StringSegment[] { "你", "好,, 世, ,\t,\r\n , 界" } - }, - }; - } - } - - public static TheoryData MaxCountData - { - get - { - var data = new TheoryData(); - for (var i = 0; i < 12; i++) - { - data.Add(i, i); - } - - data.Add(12, 11); - data.Add(20, 11); - - return data; - } - } - - [Theory] - [MemberData(nameof(CountData))] - public void Count_ReturnsExpectedValue(string value, char[] separators, int expected) - { - // Arrange - var tokenizer = new TrimmingTokenizer(value, separators); - - // Act - var actual = tokenizer.Count; - - // Assert - Assert.Equal(expected, actual); - } - - [Theory] - [MemberData(nameof(CountMax2Data))] - public void Count_ReturnsExpectedValue_WithMaxCount2(string value, char[] separators, int expected) - { - // Arrange - var tokenizer = new TrimmingTokenizer(value, separators, maxCount: 2); - - // Act - var actual = tokenizer.Count; - - // Assert - Assert.Equal(expected, actual); - } - - [Theory] - [MemberData(nameof(EnumeratorData))] - public void SegmentEnumerator_ReturnsExpectedValues(string value, char[] separators, StringSegment[] expected) - { - // Arrange - var segment = (StringSegment)value; - var tokenizer = new TrimmingTokenizer(segment, separators); - - // Act - var actual = tokenizer.ToArray(); - - // Assert - Assert.Equal(expected, actual); - } - - [Theory] - [MemberData(nameof(EnumeratorData))] - public void StringEnumerator_ReturnsExpectedValues(string value, char[] separators, StringSegment[] expected) - { - // Arrange - var tokenizer = new TrimmingTokenizer(value, separators); - - // Act - var actual = tokenizer.ToArray(); - - // Assert - Assert.Equal(expected, actual); - } - - [Theory] - [MemberData(nameof(EnumeratorMax2Data))] - public void SegmentEnumerator_ReturnsExpectedValues_WithMaxCount2( - string value, - char[] separators, - StringSegment[] expected) - { - // Arrange - var segment = (StringSegment)value; - var tokenizer = new TrimmingTokenizer(segment, separators, maxCount: 2); - - // Act - var actual = tokenizer.ToArray(); - - // Assert - Assert.Equal(expected, actual); - } - - [Theory] - [MemberData(nameof(EnumeratorMax2Data))] - public void StringEnumerator_ReturnsExpectedValues_WithMaxCount2( - string value, - char[] separators, - StringSegment[] expected) - { - // Arrange - var tokenizer = new TrimmingTokenizer(value, separators, maxCount: 2); - - // Act - var actual = tokenizer.ToArray(); - - // Assert - Assert.Equal(expected, actual); - } - - [Theory] - [MemberData(nameof(MaxCountData))] - public void Count_ReturnsExpectedValue_WithMaxCount(int maxCount, int expetedCount) - { - // Arrange - var tokenizer = new TrimmingTokenizer(" , , , a, , , , b, c, , , ", new[] { ' ' }, maxCount); - - // Act - var actual = tokenizer.Count; - - // Assert - Assert.Equal(expetedCount, actual); - } - } -} diff --git a/test/Microsoft.AspNetCore.shared.Test/Microsoft.AspNetCore.WebHooks.shared.Test.csproj b/test/Microsoft.AspNetCore.shared.Test/Microsoft.AspNetCore.WebHooks.shared.Test.csproj deleted file mode 100644 index e52427c..0000000 --- a/test/Microsoft.AspNetCore.shared.Test/Microsoft.AspNetCore.WebHooks.shared.Test.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - $(Configurations);CodeAnalysis - netcoreapp2.0;net461 - - - - - - - - - - - Utilities\TrimmingTokenizer.cs - - - diff --git a/tools/Directory.Build.props b/tools/Directory.Build.props deleted file mode 100644 index 804dfd4..0000000 --- a/tools/Directory.Build.props +++ /dev/null @@ -1,7 +0,0 @@ - - - - - <_ImportParentFile>false - - \ No newline at end of file