kontent-ai / aspnetcore-extensions Goto Github PK
View Code? Open in Web Editor NEWASP.NET Core extensions for Kontent.ai apps.
Home Page: https://www.nuget.org/packages/Kontent.Ai.AspNetCore
License: MIT License
ASP.NET Core extensions for Kontent.ai apps.
Home Page: https://www.nuget.org/packages/Kontent.Ai.AspNetCore
License: MIT License
Why is this feature required? What problems does it solve?
Until last week, we had only webhook, which now is legacy webhook. This webhook used the class DeliveryWebhookModel. We don't have a class for the new webhook which is using different naming for properties.
An ideal solution for the above problems would be to create a class for the new webhook type so all the projects that use this webhook won't be required to create a new class in each project.
Webhooks in Kentico Kontent can only define one secret webhook key per URL. As such we have had to make multiple end point definitions in dev / test. In addition due to the issue of no distributed caching ability we have had to make multiple webhook endpoints to identify each node of a load balanced cluster.
This necessitates multiple webhook secrets to be defined in a configuration file.
Here is an example:
We solved this by allowing multiple webhook secrets to be defined as follows:
public async Task InvokeAsync(HttpContext httpContext, IOptions<ProjectOptionsBase> projectOptions)
{
var request = httpContext.Request;
request.EnableBuffering();
using var reader = new StreamReader(request.Body, Encoding.UTF8, true, 1024, true);
var content = await reader.ReadToEndAsync();
request.Body.Seek(0, SeekOrigin.Begin);
// Iterates through all secrets to allow us to use multiple Kentico projects content.
var generatedSignatures = new List<string>();
foreach (var sig in projectOptions.Value.KenticoKontentWebhookSecrets)
generatedSignatures.Add(GenerateHash(content, sig));
var signature = request.Headers["X-KC-Signature"].FirstOrDefault();
if (!generatedSignatures.Contains(signature))
{
httpContext.Response.StatusCode = 401;
return;
}
await _next(httpContext);
}
Easy fix would be to do the same thing, and make your WebhookOptions model be an array of strings so you could define them in a config file as follows:
"KenticoKontentWebhookSecrets": [
".....", // Matt's ARRT.ORG Ngrok Dev Endpoint
".....", // Chris ARRT.ORG NGrok Dev Endpoint
".....", //cdevwww2hook.arrt.org
"....." //tdevwww2hook.arrt.org
],
https://kontent.ai/learn/docs/webhooks/webhooks/net details a new webhook experience.
However, this library appears to still use X-KC-Signature HTTP header for the webhook signature validator.
It appears the new HTTP Header is "X-Kontent-ai-Signature".
Create a new signature validator and differentiate the current one as "legacy" perhaps?
Directory.Build.props
with -p:NuspecProperties="Version=${{ steps.get_version.outputs.version-without-v }}
dotnet build -p:Version=1.2.3
and dotnet pack -p:PackageVersion=1.2.3
does the trick/p:CoverletOutputFormat=opencover
Examples from AppVeyor:
<Project><PropertyGroup><Version>$($ENV:APPVEYOR_BUILD_VERSION)</Version></PropertyGroup></Project>" | out-file "Directory.build.props
(before build)
And:
dotnet_csproj:
patch: true
file: '**\*.csproj'
version: '{version}'
version_prefix: '{version}'
package_version: '{version}'
assembly_version: '{version}'
file_version: '{version}'
informational_version: '{version}'
$buildConfig = if ($ENV:CONFIGURATION -eq $null) { "Release" } else { $ENV:CONFIGURATION }
$buildFolder = if ($ENV:APPVEYOR_BUILD_FOLDER -eq $null) { $PSScriptRoot } else { $ENV:APPVEYOR_BUILD_FOLDER }
$openCover = 'C:\ProgramData\chocolatey\lib\opencover.portable\tools\OpenCover.Console.exe'
$target = '-target:C:\Program Files\dotnet\dotnet.exe'
$targetArgs = '-targetargs:"test -c:' + $buildConfig + ' --logger:trx;LogFileName=results.trx --filter FullyQualifiedName!~Benchmarks /p:DebugType=full"'
$filter = '-filter:+[Kentico.Kontent.Delivery*]*-[*Tests]*-[*Benchmarks]*'
$output = '-output:' + $buildFolder + '\coverage.xml'
$register = if ($ENV:APPVEYOR -eq $true ) { '-register' } else { '-register:user' } # Magical parameter that breaks things
& $openCover $target $targetArgs $filter $register '-oldStyle' '-mergeoutput' $output
warning NU5048: The 'PackageIconUrl'/'iconUrl' element is deprecated. Consider using the 'PackageIcon'/'icon' element instead. Learn more at https://aka.ms/deprecateIconUrl
Currently, there is zero coverage for ~/ImageTransformation
code.
Cover at least a happy path by tests.
https://docs.microsoft.com/en-us/aspnet/core/test/middleware
Deserializing webhook payloads via WebhookModel
does not work with various payloads. As an example, the following payload as the result of a publish event is fine:
{
"data": {
"items": [
{
"id": "46763b84-ac6d-4347-b18a-41f8ece0badd",
"codename": "test_publish_published_webhook",
"language": "default",
"type": "publish_test",
"collection": "default"
}
],
"taxonomies": []
},
"message": {
"id": "ce7bd31a-411e-4a54-af1c-7fa46bb7c1f5",
"project_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
"type": "content_item_variant",
"operation": "publish",
"api_name": "delivery_production",
"created_timestamp": "2022-04-12T16:02:27.0593617Z",
"webhook_url": "https://routing.azurewebsites.net/api/KontentWebhook"
}
}
whereas the payload for a workflow event change does not:
{
"data": {
"items": [
{
"item": {
"id": "66d00376-ee1d-4ed1-9a3c-a88110e65190"
},
"language": {
"id": "00000000-0000-0000-0000-000000000000"
},
"transition_from": {
"id": "fe59bae0-ead6-4145-9ea8-acb398218338"
},
"transition_to": {
"id": "02907d8d-2639-432a-9ea7-633f9e3e050e"
}
}
]
},
"message": {
"id": "a94ff0a8-39cb-4975-9b65-ba7ba7305693",
"project_id": "513fdcd0-795a-01d5-a3d4-97bb0ad9c331",
"type": "content_item_variant",
"operation": "change_workflow_step",
"api_name": "content_management",
"created_timestamp": "2022-04-12T13:39:34.4449999Z",
"webhook_url": "https://45d3-84-67-20-182.ngrok.io/webhooks/webhooks"
}
}
There are two issues with the above:
"language":{"id": "00000000-0000-0000-0000-000000000000"}
, but in the c# class is a string and causes a JSON exception when deserializing: The JSON value could not be converted to System.String. Path: $.data.items[0].language | LineNumber: 0 | BytePositionInLine: 84.Also of interest are that the language
element in both of the above messages are different; the publish event uses a codename, whereas the workflow change uses a reference identifier.
Replicated in LINQPad 7, using .NET 6, System.Text.Json, and Kentico.Kontent.AspNetCore 0.12.0-beta3
void Main()
{
"publish".Dump();
var model = System.Text.Json.JsonSerializer.Deserialize<WebhookModel>(publishJson);
model.Dump();
model = System.Text.Json.JsonSerializer.Deserialize<WebhookModel>(workflowJson);
model.Dump();
}
// You can define other methods, fields, classes and namespaces here
string publishJson = "{\"data\":{\"items\":[{\"id\":\"46763b84-ac6d-4347-b18a-41f8ece0badd\",\"codename\":\"test_publish_published_webhook\",\"language\":\"default\",\"type\":\"publish_test\",\"collection\":\"default\"}],\"taxonomies\":[]},\"message\":{\"id\":\"ce7bd31a-411e-4a54-af1c-7fa46bb7c1f5\",\"project_id\":\"aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa\",\"type\":\"content_item_variant\",\"operation\":\"publish\",\"api_name\":\"delivery_production\",\"created_timestamp\":\"2022-04-12T16:02:27.0593617Z\",\"webhook_url\":\"https://routing.azurewebsites.net/api/KontentWebhook\"}}";
string workflowJson = "{\"data\":{\"items\":[{\"item\":{\"id\":\"66d00376-ee1d-4ed1-9a3c-a88110e65190\"},\"language\":{\"id\":\"00000000-0000-0000-0000-000000000000\"}}]},\"message\":{\"id\":\"a94ff0a8-39cb-4975-9b65-ba7ba7305693\",\"project_id\":\"aaaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa\",\"type\":\"content_item_variant\",\"operation\":\"change_workflow_step\",\"api_name\":\"content_management\",\"created_timestamp\":\"2022-04-12T13:39:34.4449999Z\",\"webhook_url\":\"https://45d3-84-67-20-182.ngrok.io/webhooks/webhooks\"}}";
Model should be consistent and should deserialize correctly
Add links to screenshots, if possible.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.