Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added deliveries workspace view to the webhook details workspace #18175

Merged
merged 40 commits into from
Feb 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
d8c8f2b
Added deliveries workspace view to the webhook details workspace.
AndyButland Jan 30, 2025
4e2703f
Front-end linting fixes.
AndyButland Jan 30, 2025
6df96de
rename to unique
madsrasmussen Jan 31, 2025
f0e80cd
update filter value
madsrasmussen Jan 31, 2025
2d577da
make delivery feature folder
madsrasmussen Jan 31, 2025
c4f2725
move delivery workspace view for delivery feature folder
madsrasmussen Jan 31, 2025
e0602fc
correct details workspace view label and pathname to match name
madsrasmussen Jan 31, 2025
8d14612
remove unused alias
madsrasmussen Jan 31, 2025
b47edc1
use singular form to align naming
madsrasmussen Jan 31, 2025
cf948f3
remove pagination as the default collection kind already includes this
madsrasmussen Jan 31, 2025
5ff190f
show icon
madsrasmussen Jan 31, 2025
1c93c48
Merge branch 'v15/dev' into v15/feature/webhook-deliveries-workspace-…
madsrasmussen Feb 3, 2025
c31be71
remove double registration
madsrasmussen Feb 3, 2025
19c54dc
add observables for webhook data, add get methods + add jsdocs
madsrasmussen Feb 3, 2025
1cd62ec
align UX with languages
madsrasmussen Feb 3, 2025
134e6b0
remove hardcoded fake name + make url the link
madsrasmussen Feb 3, 2025
4a21b14
remove redundant url in table
madsrasmussen Feb 3, 2025
f379586
render status code as tag
madsrasmussen Feb 3, 2025
66f3a8b
use tags for enabled/disabled webhook state to align with users
madsrasmussen Feb 3, 2025
641ff6e
make the name more explicit
madsrasmussen Feb 3, 2025
ba4b3b0
move webhook root to a feature folder
madsrasmussen Feb 3, 2025
f3fb944
export consts
madsrasmussen Feb 3, 2025
0ae4ea2
fix webhook collection pagination
madsrasmussen Feb 3, 2025
1693adb
move menu item manifests into root folder
madsrasmussen Feb 3, 2025
f919a3c
move webhook delivery filering responsibility from repo to workspace …
madsrasmussen Feb 3, 2025
64ee7d4
reorganize
madsrasmussen Feb 3, 2025
f24d655
move workspace
madsrasmussen Feb 3, 2025
3479164
fix import
madsrasmussen Feb 3, 2025
457b0c9
move entity actions
madsrasmussen Feb 3, 2025
81d0ec0
export delivery consts
madsrasmussen Feb 3, 2025
f1f34c3
dot not export const
madsrasmussen Feb 3, 2025
00bdcad
rename folder
madsrasmussen Feb 3, 2025
9e73d36
update name
madsrasmussen Feb 3, 2025
fc10b3b
make event feature folder
madsrasmussen Feb 3, 2025
f97fe2c
export consts
madsrasmussen Feb 3, 2025
f626fa4
move repository files
madsrasmussen Feb 3, 2025
7cb5146
more clean up
madsrasmussen Feb 3, 2025
d260fd2
split types
madsrasmussen Feb 3, 2025
27f170c
add deprecation warning for a temp method
madsrasmussen Feb 3, 2025
5efa888
bring back url to deliveries table
madsrasmussen Feb 3, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public async Task<ActionResult<PagedViewModel<WebhookResponseModel>>> All(
var viewModel = new PagedViewModel<WebhookResponseModel>
{
Total = result.Total,
Items = webhooks.Select(x => _webhookPresentationFactory.CreateResponseModel(x)),
Items = webhooks.Select(_webhookPresentationFactory.CreateResponseModel),
};

return Ok(viewModel);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using Asp.Versioning;
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Common.ViewModels.Pagination;
using Umbraco.Cms.Api.Management.Factories;
using Umbraco.Cms.Api.Management.ViewModels.Webhook;
using Umbraco.Cms.Api.Management.ViewModels.Webhook.Logs;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;
Expand All @@ -23,12 +23,11 @@ public AllWebhookLogController(IWebhookLogService webhookLogService, IWebhookPre

[HttpGet("logs")]
[MapToApiVersion("1.0")]
[ProducesResponseType(typeof(WebhookResponseModel), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(PagedViewModel<WebhookLogResponseModel>), StatusCodes.Status200OK)]
public async Task<IActionResult> Logs(CancellationToken cancellationToken, int skip = 0, int take = 100)
{
PagedModel<WebhookLog> logs = await _webhookLogService.Get(skip, take);
IEnumerable<WebhookLogResponseModel> logResponseModels = logs.Items.Select(x => _webhookPresentationFactory.CreateResponseModel(x));
return Ok(logResponseModels);
PagedViewModel<WebhookLogResponseModel> viewModel = CreatePagedWebhookLogResponseModel(logs, _webhookPresentationFactory);
return Ok(viewModel);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Common.ViewModels.Pagination;
using Umbraco.Cms.Api.Management.Factories;
using Umbraco.Cms.Api.Management.ViewModels.Webhook.Logs;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;

namespace Umbraco.Cms.Api.Management.Controllers.Webhook.Logs;

[ApiVersion("1.0")]
public class WebhookLogController : WebhookLogControllerBase
{
private readonly IWebhookLogService _webhookLogService;
private readonly IWebhookPresentationFactory _webhookPresentationFactory;

public WebhookLogController(IWebhookLogService webhookLogService, IWebhookPresentationFactory webhookPresentationFactory)
{
_webhookLogService = webhookLogService;
_webhookPresentationFactory = webhookPresentationFactory;
}

[HttpGet("{id:guid}/logs")]
[MapToApiVersion("1.0")]
[ProducesResponseType(typeof(PagedViewModel<WebhookLogResponseModel>), StatusCodes.Status200OK)]
public async Task<IActionResult> Logs(CancellationToken cancellationToken, Guid id, int skip = 0, int take = 100)
{
PagedModel<WebhookLog> logs = await _webhookLogService.Get(id, skip, take);
PagedViewModel<WebhookLogResponseModel> viewModel = CreatePagedWebhookLogResponseModel(logs, _webhookPresentationFactory);
return Ok(viewModel);
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Common.ViewModels.Pagination;
using Umbraco.Cms.Api.Management.Factories;
using Umbraco.Cms.Api.Management.Routing;
using Umbraco.Cms.Api.Management.ViewModels.Webhook.Logs;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;

namespace Umbraco.Cms.Api.Management.Controllers.Webhook.Logs;

[VersionedApiBackOfficeRoute($"{Constants.UdiEntityType.Webhook}")]
[ApiExplorerSettings(GroupName = "Webhook")]
public class WebhookLogControllerBase : ManagementApiControllerBase;
public class WebhookLogControllerBase : ManagementApiControllerBase
{
protected PagedViewModel<WebhookLogResponseModel> CreatePagedWebhookLogResponseModel(PagedModel<WebhookLog> logs, IWebhookPresentationFactory webhookPresentationFactory)
{
WebhookLogResponseModel[] logResponseModels = logs.Items.Select(webhookPresentationFactory.CreateResponseModel).ToArray();

return new PagedViewModel<WebhookLogResponseModel>
{
Total = logs.Total,
Items = logResponseModels,
};
}

}
159 changes: 147 additions & 12 deletions src/Umbraco.Cms.Api.Management/OpenApi.json
Original file line number Diff line number Diff line change
Expand Up @@ -33846,13 +33846,22 @@
]
}
},
"/umbraco/management/api/v1/webhook/events": {
"/umbraco/management/api/v1/webhook/{id}/logs": {
"get": {
"tags": [
"Webhook"
],
"operationId": "GetWebhookEvents",
"operationId": "GetWebhookByIdLogs",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "skip",
"in": "query",
Expand Down Expand Up @@ -33880,7 +33889,7 @@
"schema": {
"oneOf": [
{
"$ref": "#/components/schemas/PagedWebhookEventModel"
"$ref": "#/components/schemas/PagedWebhookLogResponseModel"
}
]
}
Expand All @@ -33889,9 +33898,6 @@
},
"401": {
"description": "The resource is protected and requires an authentication token"
},
"403": {
"description": "The authenticated user do not have access to this resource"
}
},
"security": [
Expand All @@ -33901,12 +33907,12 @@
]
}
},
"/umbraco/management/api/v1/webhook/logs": {
"/umbraco/management/api/v1/webhook/events": {
"get": {
"tags": [
"Webhook"
],
"operationId": "GetWebhookLogs",
"operationId": "GetWebhookEvents",
"parameters": [
{
"name": "skip",
Expand Down Expand Up @@ -33935,21 +33941,62 @@
"schema": {
"oneOf": [
{
"$ref": "#/components/schemas/WebhookResponseModel"
"$ref": "#/components/schemas/PagedWebhookEventModel"
}
]
}
}
}
},
"404": {
"description": "Not Found",
"401": {
"description": "The resource is protected and requires an authentication token"
},
"403": {
"description": "The authenticated user do not have access to this resource"
}
},
"security": [
{
"Backoffice User": [ ]
}
]
}
},
"/umbraco/management/api/v1/webhook/logs": {
"get": {
"tags": [
"Webhook"
],
"operationId": "GetWebhookLogs",
"parameters": [
{
"name": "skip",
"in": "query",
"schema": {
"type": "integer",
"format": "int32",
"default": 0
}
},
{
"name": "take",
"in": "query",
"schema": {
"type": "integer",
"format": "int32",
"default": 100
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"oneOf": [
{
"$ref": "#/components/schemas/ProblemDetails"
"$ref": "#/components/schemas/PagedWebhookLogResponseModel"
}
]
}
Expand Down Expand Up @@ -42320,6 +42367,30 @@
},
"additionalProperties": false
},
"PagedWebhookLogResponseModel": {
"required": [
"items",
"total"
],
"type": "object",
"properties": {
"total": {
"type": "integer",
"format": "int64"
},
"items": {
"type": "array",
"items": {
"oneOf": [
{
"$ref": "#/components/schemas/WebhookLogResponseModel"
}
]
}
}
},
"additionalProperties": false
},
"PagedWebhookResponseModel": {
"required": [
"items",
Expand Down Expand Up @@ -46190,6 +46261,70 @@
},
"additionalProperties": false
},
"WebhookLogResponseModel": {
"required": [
"date",
"eventAlias",
"exceptionOccured",
"isSuccessStatusCode",
"key",
"requestBody",
"requestHeaders",
"responseBody",
"responseHeaders",
"retryCount",
"statusCode",
"url",
"webhookKey"
],
"type": "object",
"properties": {
"key": {
"type": "string",
"format": "uuid"
},
"webhookKey": {
"type": "string",
"format": "uuid"
},
"statusCode": {
"type": "string"
},
"isSuccessStatusCode": {
"type": "boolean"
},
"date": {
"type": "string",
"format": "date-time"
},
"eventAlias": {
"type": "string"
},
"url": {
"type": "string"
},
"retryCount": {
"type": "integer",
"format": "int32"
},
"requestHeaders": {
"type": "string"
},
"requestBody": {
"type": "string"
},
"responseHeaders": {
"type": "string"
},
"responseBody": {
"type": "string"
},
"exceptionOccured": {
"type": "boolean"
}
},
"additionalProperties": false
},
"WebhookResponseModel": {
"required": [
"contentTypeKeys",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models;

namespace Umbraco.Cms.Core.Persistence.Repositories;

Expand All @@ -8,6 +8,17 @@ public interface IWebhookLogRepository

Task<PagedModel<WebhookLog>> GetPagedAsync(int skip, int take);

// TODO (V16): Remove the default implementation on this method.
async Task<PagedModel<WebhookLog>> GetPagedAsync(Guid webhookKey, int skip, int take)
{
// This is very inefficient as the filter/skip/take is in-memory, but it will return the correct data.
// As it's only here to avoid a breaking change on the interface that is unlikely to have a custom
// implementation, this seems reasonable.
PagedModel<WebhookLog> allLogs = await GetPagedAsync(0, int.MaxValue);
var logsForId = allLogs.Items.Where(x => x.WebhookKey == webhookKey).ToList();
return new PagedModel<WebhookLog>(logsForId.Count, logsForId.Skip(skip).Take(take));
}

Task<IEnumerable<WebhookLog>> GetOlderThanDate(DateTime date);

Task DeleteByIds(int[] ids);
Expand Down
14 changes: 12 additions & 2 deletions src/Umbraco.Core/Services/IWebhookLogService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Webhooks;
using Umbraco.Cms.Core.Models;

namespace Umbraco.Cms.Core.Services;

Expand All @@ -8,4 +7,15 @@ public interface IWebhookLogService
Task<WebhookLog> CreateAsync(WebhookLog webhookLog);

Task<PagedModel<WebhookLog>> Get(int skip = 0, int take = int.MaxValue);

// TODO (V16): Remove the default implementation on this method.
async Task<PagedModel<WebhookLog>> Get(Guid webhookKey, int skip = 0, int take = int.MaxValue)
{
// This is very inefficient as the filter/skip/take is in-memory, but it will return the correct data.
// As it's only here to avoid a breaking change on the interface that is unlikely to have a custom
// implementation, this seems reasonable.
PagedModel<WebhookLog> allLogs = await Get(0, int.MaxValue);
var logsForId = allLogs.Items.Where(x => x.WebhookKey == webhookKey).ToList();
return new PagedModel<WebhookLog>(logsForId.Count, logsForId.Skip(skip).Take(take));
}
}
9 changes: 7 additions & 2 deletions src/Umbraco.Core/Services/WebhookLogService.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Persistence.Repositories;
using Umbraco.Cms.Core.Scoping;
using Umbraco.Cms.Core.Webhooks;

namespace Umbraco.Cms.Core.Services;

Expand Down Expand Up @@ -30,4 +29,10 @@ public async Task<PagedModel<WebhookLog>> Get(int skip = 0, int take = int.MaxVa
using ICoreScope scope = _coreScopeProvider.CreateCoreScope(autoComplete: true);
return await _webhookLogRepository.GetPagedAsync(skip, take);
}

public async Task<PagedModel<WebhookLog>> Get(Guid webhookKey, int skip = 0, int take = int.MaxValue)
{
using ICoreScope scope = _coreScopeProvider.CreateCoreScope(autoComplete: true);
return await _webhookLogRepository.GetPagedAsync(webhookKey, skip, take);
}
}
Loading
Loading