Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/Umbraco.Core/Models/WebhookLog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,6 @@ public class WebhookLog
public string ResponseBody { get; set; } = string.Empty;

public bool ExceptionOccured { get; set; }

public bool IsSuccessStatusCode { get; set; }
}
5 changes: 3 additions & 2 deletions src/Umbraco.Core/Services/WebhookLogFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@ public async Task<WebhookLog> CreateAsync(string eventAlias, HttpRequestMessage
Url = webhook.Url,
WebhookKey = webhook.Key,
RetryCount = retryCount,
RequestHeaders = requestMessage.Headers.ToString(),
RequestHeaders = $"{requestMessage.Content?.Headers}{requestMessage.Headers}",
RequestBody = await requestMessage.Content?.ReadAsStringAsync(cancellationToken)!,
ExceptionOccured = exception is not null,
};

if (httpResponseMessage is not null)
{
log.StatusCode = MapStatusCodeToMessage(httpResponseMessage.StatusCode);
log.ResponseHeaders = httpResponseMessage.Headers.ToString();
log.IsSuccessStatusCode = httpResponseMessage.IsSuccessStatusCode;
log.ResponseHeaders = $"{httpResponseMessage.Content.Headers}{httpResponseMessage.Headers}";
log.ResponseBody = await httpResponseMessage.Content.ReadAsStringAsync(cancellationToken);
}
else if (exception is HttpRequestException httpRequestException)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Umbraco.Cms.Core.Models;
using System.Text.RegularExpressions;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Webhooks;
using Umbraco.Cms.Infrastructure.Persistence.Dtos;

Expand Down Expand Up @@ -33,6 +34,7 @@ public static WebhookLog DtoToEntity(WebhookLogDto dto) =>
ResponseBody = dto.ResponseBody,
RetryCount = dto.RetryCount,
StatusCode = dto.StatusCode,
IsSuccessStatusCode = Regex.IsMatch(dto.StatusCode, "^.*\\(2(\\d{2})\\)$"),
Key = dto.Key,
Id = dto.Id,
Url = dto.Url,
Expand Down
1 change: 1 addition & 0 deletions src/Umbraco.Web.BackOffice/Mapping/WebhookMapDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ private void Map(WebhookLog source, WebhookLogViewModel target, MapperContext co
target.Url = source.Url;
target.RequestHeaders = source.RequestHeaders;
target.WebhookKey = source.WebhookKey;
target.IsSuccessStatusCode = source.IsSuccessStatusCode;

if (_hostingEnvironment.IsDebugMode)
{
Expand Down
3 changes: 3 additions & 0 deletions src/Umbraco.Web.Common/Models/WebhookLogViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ public class WebhookLogViewModel
[DataMember(Name = "statusCode")]
public string StatusCode { get; set; } = string.Empty;

[DataMember(Name = "isSuccessStatusCode")]
public bool IsSuccessStatusCode { get; set; }

[DataMember(Name = "date")]
public DateTime Date { get; set; }

Expand Down
26 changes: 21 additions & 5 deletions src/Umbraco.Web.UI.Client/src/views/webhooks/logs.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@

const vm = this;

vm.pagination = {
pageNumber: 1,
pageSize: 25
};

vm.logs = [];
vm.openLogOverlay = openLogOverlay;
vm.isChecked = isChecked;

function init() {
vm.loading = true;
Expand All @@ -22,9 +26,14 @@
}

function loadLogs() {
return webhooksResource.getLogs()
const take = vm.pagination.pageSize;
const skip = (vm.pagination.pageNumber - 1) * take;

return webhooksResource.getLogs(skip, take)
.then(data => {
vm.logs = data.items;
vm.pagination.totalPages = Math.ceil(data.totalItems/vm.pagination.pageSize);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not for this endpoint, it uses skip/take for pagination so totalPages always returns 0

Copy link
Copy Markdown
Contributor

@bjarnef bjarnef May 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


vm.logs.forEach(log => {
formatDatesToLocal(log);
});
Expand Down Expand Up @@ -54,9 +63,16 @@
editorService.open(dialog);
}

function isChecked(log) {
return log.statusCode === "OK (200)";
}
vm.previousPage = () => vm.goToPage(vm.pagination.pageNumber - 1);
vm.nextPage = () => vm.goToPage(vm.pagination.pageNumber + 1);

vm.goToPage = (pageNumber) => {
vm.pagination.pageNumber = pageNumber;
vm.loading = true;
loadLogs().then(() => {
vm.loading = false;
});
};

init();
}
Expand Down
23 changes: 17 additions & 6 deletions src/Umbraco.Web.UI.Client/src/views/webhooks/logs.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
<thead>
<tr>
<th></th>
<th><localize key="webhooks_webhookKey">Webhook key</localize></th>
<th><localize key="general_date">Date</localize></th>
<th><localize key="webhooks_url">Url</localize></th>
<th><localize key="webhooks_event">Event</localize></th>
Expand All @@ -14,18 +13,30 @@
<tr ng-repeat="log in vm.logs track by log.key" ng-click="vm.openLogOverlay(log)" style="cursor: pointer;">
<td style="width: 20px;">
<umb-checkmark
ng-if="vm.isChecked(log)"
checked="vm.isChecked(log)"
size="m">
ng-if="log.isSuccessStatusCode"
checked="true"
size="m"
title="{{ log.statusCode }}">
</umb-checkmark>
<umb-icon icon="icon-wrong" class="umb-checkmark umb-checkmark--m" style="cursor: default;" ng-if="!vm.isChecked(log)"></umb-icon>
<umb-icon icon="icon-wrong" class="umb-checkmark umb-checkmark--m" style="cursor: default;" ng-if="!log.isSuccessStatusCode" title="{{ log.statusCode }}"></umb-icon>
</td>
<td>{{ log.webhookKey }}</td>
<td>{{ log.formattedLogDate }}</td>
<td>{{ log.url }}</td>
<td>{{ log.eventAlias }}</td>
<td>{{ log.retryCount }}</td>
</tr>
</tbody>
</table>

<umb-empty-state ng-hide="vm.logs.length" position="center">
<localize key="content_listViewNoItems">There are no items show in the list.</localize>
</umb-empty-state>

<umb-pagination
page-number="vm.pagination.pageNumber"
total-pages="vm.pagination.totalPages"
on-next="vm.nextPage"
on-prev="vm.previousPage"
on-go-to-page="vm.goToPage">
</umb-pagination>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@

vm.close = close;
vm.formatData = formatData;
vm.detectLanguage = detectLanguage;

function formatData(data) {

let obj = data;

if (data.detectIsJson()) {
try {
obj = Utilities.fromJson(data)
obj = JSON.stringify(Utilities.fromJson(data), null, 2);
} catch (err) {
obj = data;
}
Expand All @@ -21,6 +22,21 @@
return obj;
}

function detectLanguage(headers, defaultLanguage) {
const matches = headers.match(/^Content-Type:\s*(?<type>[a-z\/+.-]+)(\;?.*?)$/mi)
if (matches) {
const contentType = matches.groups["type"];
if (contentType === "application/json")
return "JSON";
if (contentType === "text/html")
return "HTML";
if (contentType === "application/xml" || contentType === "text/xml")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we include application/rss+xml and application/atom+xml as well?
Not sure how common it is with webhooks, but I guess to potentially could:
https://community.zapier.com/code-webhooks-52/rss-feed-trigger-app-returns-not-acceptable-28640

return "XML";
}

return defaultLanguage || "TEXT";
}

function close() {
if ($scope.model && $scope.model.close) {
$scope.model.close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
<div class="flex items-center">
<div class="flx-g0 flx-s0" style="flex-basis: 40px;">
<umb-checkmark checked="true" size="m" style="cursor: default"
ng-if="model.log.statusCode === 'OK (200)'"></umb-checkmark>
ng-if="model.log.isSuccessStatusCode"></umb-checkmark>
<umb-icon icon="icon-wrong" class="umb-checkmark umb-checkmark--m" style="cursor: default;"
ng-if="model.log.statusCode !== 'OK (200)'"></umb-icon>
ng-if="!model.log.isSuccessStatusCode"></umb-icon>
</div>
<div class="flx-g1 flx-s1 flx-b2">{{model.log.statusCode}}</div>
</div>
Expand All @@ -45,6 +45,10 @@
<div>{{model.log.retryCount}}</div>
</umb-control-group>

<umb-control-group label="Webhook key">
<div>{{model.log.webhookKey}}</div>
</umb-control-group>

</umb-box-content>

</umb-box>
Expand All @@ -53,16 +57,14 @@
<umb-box-header title="Request"></umb-box-header>
<umb-box-content class="block-form">
<pre class="code">{{model.log.requestHeaders}}</pre>
<umb-code-snippet language="'JSON'" wrap="true">{{vm.formatData(model.log.requestBody) | json}}
</umb-code-snippet>
<umb-code-snippet language="vm.detectLanguage(model.log.requestHeaders, 'JSON')" wrap="true">{{vm.formatData(model.log.requestBody)}}</umb-code-snippet>
</umb-box-content>
</umb-box>
<umb-box>
<umb-box-header title="Response"></umb-box-header>
<umb-box-content class="block-form">
<pre class="code">{{model.log.responseHeaders}}</pre>
<umb-code-snippet language="'TEXT'" wrap="true">{{vm.formatData(model.log.responseBody) | json}}
</umb-code-snippet>
<umb-code-snippet language="vm.detectLanguage(model.log.responseHeaders)" wrap="true">{{vm.formatData(model.log.responseBody)}}</umb-code-snippet>
</umb-box-content>
</umb-box>
<div ng-if="model.log.exceptionOccured">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
vm.page.name = "";
vm.page.navigation = [];

let webhookUri = $routeParams.method;
let webhookUri = $routeParams.id;

onInit();

Expand All @@ -33,8 +33,8 @@
{
"name": vm.page.labels.webhooks,
"icon": "icon-webhook",
"view": "views/webhooks/webhooks.html",
"active": webhookUri === 'overview',
"view": !webhookUri ? "views/webhooks/webhooks.html" : null,
"active": !webhookUri,
"alias": "umbWebhooks",
"action": function () {
$location.path("/settings/webhooks/overview");
Expand All @@ -43,11 +43,11 @@
{
"name": vm.page.labels.logs,
"icon": "icon-box-alt",
"view": "views/webhooks/logs.html",
"view": webhookUri === 'logs' ? "views/webhooks/logs.html" : null,
"active": webhookUri === 'logs',
"alias": "umbWebhookLogs",
"action": function () {
$location.path("/settings/webhooks/overview");
$location.path("/settings/webhooks/overview/logs");
}
}
];
Expand Down