Relations/types mangement api cleanup (#15910)

* Made Relation types read only trough the management api

* Removed path from RelationTypeResponseModel

* Removed RelationTypes tree controllers

* Deleted ByChildRelationController as the usecase has been internalized

* Reworked RelationResponseModel

* Added the ID the toe relation response model

* RelationType.IsDeletable is no longer relevant for the management api

Since types are only managed trough code.

* Removed RelationType create/update leftovers

Brought RelationType responsemodels more in line with similar models
Update openapi spec

* Review improvements

* Renamed controller file to match class name

---------

Co-authored-by: Sven Geusens <sge@umbraco.dk>
Co-authored-by: Mads Rasmussen <madsr@hey.com>
Co-authored-by: kjac <kja@umbraco.dk>
This commit is contained in:
Sven Geusens
2024-03-27 10:01:29 +01:00
committed by GitHub
parent e1ee896556
commit 1fdc0e2582
18 changed files with 181 additions and 873 deletions

View File

@@ -1,50 +0,0 @@
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Api.Management.Factories;
using Umbraco.Cms.Api.Common.ViewModels.Pagination;
using Umbraco.Cms.Api.Management.ViewModels.Relation;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Services.OperationStatus;
using Umbraco.Extensions;
namespace Umbraco.Cms.Api.Management.Controllers.Relation;
[ApiVersion("1.0")]
public class ByChildRelationController : RelationControllerBase
{
private readonly IRelationService _relationService;
private readonly IRelationPresentationFactory _relationPresentationFactory;
public ByChildRelationController(
IRelationService relationService,
IRelationPresentationFactory relationPresentationFactory)
{
_relationService = relationService;
_relationPresentationFactory = relationPresentationFactory;
}
/// <summary>
/// Gets a paged list of relations by the unique relation child keys.
/// </summary>
/// <remarks>
/// Use case: When you wanna restore a deleted item, this is used to find the old location
/// </remarks>
[HttpGet("child-relation/{childId:guid}")]
[MapToApiVersion("1.0")]
[ProducesResponseType(typeof(PagedViewModel<RelationResponseModel>), StatusCodes.Status200OK)]
public async Task<IActionResult> ByChild(Guid childId, int skip = 0, int take = 100, string? relationTypeAlias = "")
{
PagedModel<IRelation> relationsAttempt = await _relationService.GetPagedByChildKeyAsync(childId, skip, take, relationTypeAlias);
IEnumerable<RelationResponseModel> mappedRelations = relationsAttempt.Items.Select(_relationPresentationFactory.Create);
return await Task.FromResult(Ok(new PagedViewModel<RelationResponseModel>
{
Total = relationsAttempt.Total,
Items = mappedRelations,
}));
}
}

View File

@@ -0,0 +1,41 @@
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Common.ViewModels.Pagination;
using Umbraco.Cms.Api.Management.ViewModels.RelationType;
using Umbraco.Cms.Core.Mapping;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;
namespace Umbraco.Cms.Api.Management.Controllers.RelationType;
[ApiVersion("1.0")]
public class AllRelationTypeController : RelationTypeControllerBase
{
private readonly IRelationService _relationService;
private readonly IUmbracoMapper _umbracoMapper;
public AllRelationTypeController(
IRelationService relationService,
IUmbracoMapper umbracoMapper)
{
_relationService = relationService;
_umbracoMapper = umbracoMapper;
}
[HttpGet]
[MapToApiVersion("1.0")]
[ProducesResponseType(typeof(PagedViewModel<RelationTypeResponseModel>), StatusCodes.Status200OK)]
public async Task<ActionResult<PagedViewModel<RelationTypeResponseModel>>> Get(int skip = 0, int take = 100)
{
PagedModel<IRelationType> allRelationTypes = await _relationService.GetPagedRelationTypesAsync(skip, take);
var pagedResult = new PagedViewModel<RelationTypeResponseModel>
{
Total = allRelationTypes.Total,
Items = _umbracoMapper.MapEnumerable<IRelationType, RelationTypeResponseModel>(allRelationTypes.Items.Skip(skip).Take(take)),
};
return Ok(pagedResult);
}
}

View File

@@ -1,44 +0,0 @@
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.Factories;
using Umbraco.Cms.Api.Management.ViewModels.RelationType;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.OperationStatus;
namespace Umbraco.Cms.Api.Management.Controllers.RelationType;
[ApiVersion("1.0")]
public class CreateRelationTypeController : RelationTypeControllerBase
{
private readonly IRelationService _relationService;
private readonly IRelationTypePresentationFactory _relationTypePresentationFactory;
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;
public CreateRelationTypeController(IRelationService relationService,
IRelationTypePresentationFactory relationTypePresentationFactory,
IBackOfficeSecurityAccessor backOfficeSecurityAccessor)
{
_relationService = relationService;
_relationTypePresentationFactory = relationTypePresentationFactory;
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
}
[HttpPost]
[MapToApiVersion("1.0")]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> Create(CreateRelationTypeRequestModel createRelationTypeRequestModel)
{
IRelationType relationTypePersisted = _relationTypePresentationFactory.CreateRelationType(createRelationTypeRequestModel);
Attempt<IRelationType, RelationTypeOperationStatus> result = await _relationService.CreateAsync(relationTypePersisted, CurrentUserKey(_backOfficeSecurityAccessor));
return result.Success
? CreatedAtId<ByKeyRelationTypeController>(controller => nameof(controller.ByKey), relationTypePersisted.Key)
: RelationTypeOperationStatusResult(result.Status);
}
}

View File

@@ -1,33 +0,0 @@
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.OperationStatus;
namespace Umbraco.Cms.Api.Management.Controllers.RelationType;
[ApiVersion("1.0")]
public class DeleteRelationTypeController : RelationTypeControllerBase
{
private readonly IRelationService _relationService;
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;
public DeleteRelationTypeController(IRelationService relationService, IBackOfficeSecurityAccessor backOfficeSecurityAccessor)
{
_relationService = relationService;
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
}
[HttpDelete("{id:guid}")]
[MapToApiVersion("1.0")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
public async Task<IActionResult> Delete(Guid id)
{
Attempt<IRelationType?, RelationTypeOperationStatus> result = await _relationService.DeleteAsync(id, CurrentUserKey(_backOfficeSecurityAccessor));
return result.Success ? await Task.FromResult(Ok()) : RelationTypeOperationStatusResult(result.Status);
}
}

View File

@@ -1,43 +0,0 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.Controllers.Tree;
using Umbraco.Cms.Api.Management.Routing;
using Umbraco.Cms.Api.Management.ViewModels;
using Umbraco.Cms.Api.Management.ViewModels.Tree;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Web.Common.Authorization;
using Umbraco.Extensions;
namespace Umbraco.Cms.Api.Management.Controllers.RelationType.Tree;
[VersionedApiBackOfficeRoute($"{Constants.Web.RoutePath.Tree}/{Constants.UdiEntityType.RelationType}")]
[ApiExplorerSettings(GroupName = "Relation Type")]
[Authorize(Policy = AuthorizationPolicies.TreeAccessRelationTypes)]
// NOTE: at the moment relation types aren't supported by EntityService, so we have little use of the
// tree controller base. We'll keep it though, in the hope that we can mend EntityService.
public class RelationTypeTreeControllerBase : NamedEntityTreeControllerBase<RelationTypeTreeItemResponseModel>
{
public RelationTypeTreeControllerBase(IEntityService entityService)
: base(entityService)
{
}
protected override UmbracoObjectTypes ItemObjectType => UmbracoObjectTypes.RelationType;
protected IEnumerable<RelationTypeTreeItemResponseModel> MapTreeItemViewModels(Guid? parentKey, IEnumerable<IRelationType> relationTypes)
=> relationTypes.Select(relationType => new RelationTypeTreeItemResponseModel
{
Name = relationType.Name!,
Id = relationType.Key,
HasChildren = false,
IsDeletable = relationType.IsDeletableRelationType(),
Parent = parentKey.HasValue
? new ReferenceByIdModel
{
Id = parentKey.Value
}
: null
});
}

View File

@@ -1,33 +0,0 @@
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Api.Common.ViewModels.Pagination;
using Umbraco.Cms.Api.Management.ViewModels.Tree;
namespace Umbraco.Cms.Api.Management.Controllers.RelationType.Tree;
[ApiVersion("1.0")]
public class RootRelationTypeTreeController : RelationTypeTreeControllerBase
{
private readonly IRelationService _relationService;
public RootRelationTypeTreeController(IEntityService entityService, IRelationService relationService)
: base(entityService) =>
_relationService = relationService;
[HttpGet("root")]
[MapToApiVersion("1.0")]
[ProducesResponseType(typeof(PagedViewModel<RelationTypeTreeItemResponseModel>), StatusCodes.Status200OK)]
public async Task<ActionResult<PagedViewModel<RelationTypeTreeItemResponseModel>>> Root(int skip = 0, int take = 100)
{
PagedModel<IRelationType> pagedRelationTypes = await _relationService.GetPagedRelationTypesAsync(skip, take);
PagedViewModel<RelationTypeTreeItemResponseModel> pagedResult = PagedViewModel(
MapTreeItemViewModels(null, pagedRelationTypes.Items),
pagedRelationTypes.Total);
return Ok(pagedResult);
}
}

View File

@@ -1,51 +0,0 @@
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.Factories;
using Umbraco.Cms.Api.Management.ViewModels.RelationType;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.OperationStatus;
namespace Umbraco.Cms.Api.Management.Controllers.RelationType;
[ApiVersion("1.0")]
public class UpdateRelationTypeController : RelationTypeControllerBase
{
private readonly IRelationService _relationService;
private readonly IRelationTypePresentationFactory _relationTypePresentationFactory;
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;
public UpdateRelationTypeController(
IRelationService relationService,
IRelationTypePresentationFactory relationTypePresentationFactory,
IBackOfficeSecurityAccessor backOfficeSecurityAccessor)
{
_relationService = relationService;
_relationTypePresentationFactory = relationTypePresentationFactory;
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
}
[HttpPut("{id:guid}")]
[MapToApiVersion("1.0")]
[ProducesResponseType(typeof(RelationTypeResponseModel), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
public async Task<IActionResult> Update(Guid id, UpdateRelationTypeRequestModel updateRelationTypeSavingViewModel)
{
IRelationType? persistedRelationType = _relationService.GetRelationTypeById(id);
if (persistedRelationType is null)
{
return RelationTypeNotFound();
}
_relationTypePresentationFactory.MapUpdateModelToRelationType(updateRelationTypeSavingViewModel, persistedRelationType);
Attempt<IRelationType, RelationTypeOperationStatus> result = await _relationService.UpdateAsync(persistedRelationType, CurrentUserKey(_backOfficeSecurityAccessor));
return result.Success ? await Task.FromResult(Ok()) : RelationTypeOperationStatusResult(result.Status);
}
}

View File

@@ -6,9 +6,5 @@ namespace Umbraco.Cms.Api.Management.Factories;
public interface IRelationTypePresentationFactory
{
IRelationType CreateRelationType(CreateRelationTypeRequestModel createRelationTypeRequestModel);
void MapUpdateModelToRelationType(UpdateRelationTypeRequestModel updateRelationTypeRequestModel, IRelationType target);
Task<IEnumerable<IReferenceResponseModel>> CreateReferenceResponseModelsAsync(IEnumerable<RelationItemModel> relationItemModels);
}

View File

@@ -1,8 +1,8 @@
using Umbraco.Cms.Core.Mapping;
using Umbraco.Cms.Api.Management.ViewModels;
using Umbraco.Cms.Api.Management.ViewModels.Relation;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.Entities;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Api.Management.ViewModels.Relation;
namespace Umbraco.Cms.Api.Management.Factories;
@@ -19,22 +19,24 @@ public class RelationPresentationFactory : IRelationPresentationFactory
public RelationResponseModel Create(IRelation relation)
{
var child = _entityService.Get(relation.ChildId)!;
var parent = _entityService.Get(relation.ParentId)!;
IEntitySlim child = _entityService.Get(relation.ChildId)!;
IEntitySlim parent = _entityService.Get(relation.ParentId)!;
RelationResponseModel relationResponseModel = new RelationResponseModel()
var relationResponseModel = new RelationResponseModel(
new ReferenceByIdModel(relation.RelationType.Key),
new RelationReferenceModel(parent.Key),
new RelationReferenceModel(child.Key))
{
ChildId = child.Key,
Id = relation.Key,
Comment = relation.Comment,
CreateDate = relation.CreateDate,
ParentId = parent.Key,
};
Tuple<IUmbracoEntity, IUmbracoEntity>? entities = _relationService.GetEntitiesFromRelation(relation);
if (entities is not null)
{
relationResponseModel.ParentName = entities.Item1.Name;
relationResponseModel.ChildName = entities.Item2.Name;
relationResponseModel.Parent.Name = entities.Item1.Name;
relationResponseModel.Child.Name = entities.Item2.Name;
}
return relationResponseModel;

View File

@@ -1,48 +1,20 @@
using Umbraco.Cms.Api.Management.ViewModels.RelationType;
using Umbraco.Cms.Api.Management.ViewModels.TrackedReferences;
using Umbraco.Cms.Api.Management.ViewModels.TrackedReferences;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Mapping;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Strings;
using Umbraco.Extensions;
namespace Umbraco.Cms.Api.Management.Factories;
public class RelationTypePresentationFactory : IRelationTypePresentationFactory
{
private readonly IShortStringHelper _shortStringHelper;
private readonly IUmbracoMapper _umbracoMapper;
public RelationTypePresentationFactory(IShortStringHelper shortStringHelper, IUmbracoMapper umbracoMapper)
public RelationTypePresentationFactory(IUmbracoMapper umbracoMapper)
{
_shortStringHelper = shortStringHelper;
_umbracoMapper = umbracoMapper;
}
public IRelationType CreateRelationType(CreateRelationTypeRequestModel createRelationTypeRequestModel) =>
new RelationType(
createRelationTypeRequestModel.Name,
createRelationTypeRequestModel.Name.ToSafeAlias(_shortStringHelper, true),
createRelationTypeRequestModel.IsBidirectional,
createRelationTypeRequestModel.ParentObjectType,
createRelationTypeRequestModel.ChildObjectType,
createRelationTypeRequestModel.IsDependency,
createRelationTypeRequestModel.Id);
public void MapUpdateModelToRelationType(UpdateRelationTypeRequestModel updateRelationTypeRequestModel, IRelationType target)
{
target.Name = updateRelationTypeRequestModel.Name;
target.Alias = updateRelationTypeRequestModel.Name.ToSafeAlias(_shortStringHelper, true);
target.ChildObjectType = updateRelationTypeRequestModel.ChildObjectType;
target.IsBidirectional = updateRelationTypeRequestModel.IsBidirectional;
if (target is IRelationTypeWithIsDependency targetWithIsDependency)
{
targetWithIsDependency.IsDependency = updateRelationTypeRequestModel.IsDependency;
}
target.ParentObjectType = updateRelationTypeRequestModel.ParentObjectType;
}
public async Task<IEnumerable<IReferenceResponseModel>> CreateReferenceResponseModelsAsync(IEnumerable<RelationItemModel> relationItemModels)
{
IReferenceResponseModel[] result = relationItemModels.Select(relationItemModel => relationItemModel.NodeType switch

View File

@@ -15,7 +15,6 @@ public class RelationTypeViewModelsMapDefinition : IMapDefinition
// Umbraco.Code.MapAll
private void Map(IRelationType source, RelationTypeResponseModel target, MapperContext context)
{
target.ChildObjectType = source.ChildObjectType;
target.IsBidirectional = source.IsBidirectional;
if (source is IRelationTypeWithIsDependency sourceWithIsDependency)
@@ -26,22 +25,18 @@ public class RelationTypeViewModelsMapDefinition : IMapDefinition
target.Id = source.Key;
target.Name = source.Name ?? string.Empty;
target.Alias = source.Alias;
target.ParentObjectType = source.ParentObjectType;
target.Path = "-1," + source.Id;
target.IsDeletable = source.IsDeletableRelationType();
target.ChildObject = MapObjectType(source.ChildObjectType);
// Set the "friendly" and entity names for the parent and child object types
if (source.ParentObjectType.HasValue)
{
UmbracoObjectTypes objType = ObjectTypes.GetUmbracoObjectType(source.ParentObjectType.Value);
target.ParentObjectTypeName = objType.GetFriendlyName();
}
if (source.ChildObjectType.HasValue)
{
UmbracoObjectTypes objType = ObjectTypes.GetUmbracoObjectType(source.ChildObjectType.Value);
target.ChildObjectTypeName = objType.GetFriendlyName();
}
target.ParentObject = MapObjectType(source.ParentObjectType);
}
private ObjectTypeResponseModel? MapObjectType(Guid? objectTypeId)
=> objectTypeId is not null
? new ObjectTypeResponseModel
{
Id = objectTypeId.Value,
Name = ObjectTypes.GetUmbracoObjectType(objectTypeId.Value).GetFriendlyName(),
}
: null;
}

View File

@@ -21654,101 +21654,48 @@
}
},
"/umbraco/management/api/v1/relation-type": {
"post": {
"get": {
"tags": [
"Relation Type"
],
"operationId": "PostRelationType",
"requestBody": {
"content": {
"application/json": {
"schema": {
"oneOf": [
{
"$ref": "#/components/schemas/CreateRelationTypeRequestModel"
}
]
}
},
"text/json": {
"schema": {
"oneOf": [
{
"$ref": "#/components/schemas/CreateRelationTypeRequestModel"
}
]
}
},
"application/*+json": {
"schema": {
"oneOf": [
{
"$ref": "#/components/schemas/CreateRelationTypeRequestModel"
}
]
}
}
}
},
"responses": {
"201": {
"description": "Created",
"headers": {
"Umb-Generated-Resource": {
"description": "Identifier of the newly created resource",
"schema": {
"type": "string",
"description": "Identifier of the newly created resource"
}
},
"Location": {
"description": "Location of the newly created resource",
"schema": {
"type": "string",
"description": "Location of the newly created resource",
"format": "uri"
}
},
"Umb-Notifications": {
"description": "The list of notifications produced during the request.",
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/NotificationHeaderModel"
},
"nullable": true
}
}
"operationId": "GetRelationType",
"parameters": [
{
"name": "skip",
"in": "query",
"schema": {
"type": "integer",
"format": "int32",
"default": 0
}
},
"400": {
"description": "Bad Request",
"headers": {
"Umb-Notifications": {
"description": "The list of notifications produced during the request.",
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/NotificationHeaderModel"
},
"nullable": true
}
}
},
{
"name": "take",
"in": "query",
"schema": {
"type": "integer",
"format": "int32",
"default": 100
}
}
],
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
"$ref": "#/components/schemas/PagedRelationTypeResponseModel"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
"$ref": "#/components/schemas/PagedRelationTypeResponseModel"
}
},
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
"$ref": "#/components/schemas/PagedRelationTypeResponseModel"
}
}
}
@@ -21843,379 +21790,6 @@
"Backoffice User": [ ]
}
]
},
"delete": {
"tags": [
"Relation Type"
],
"operationId": "DeleteRelationTypeById",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "Success",
"headers": {
"Umb-Notifications": {
"description": "The list of notifications produced during the request.",
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/NotificationHeaderModel"
},
"nullable": true
}
}
}
},
"404": {
"description": "Not Found",
"headers": {
"Umb-Notifications": {
"description": "The list of notifications produced during the request.",
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/NotificationHeaderModel"
},
"nullable": true
}
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"401": {
"description": "The resource is protected and requires an authentication token"
}
},
"security": [
{
"Backoffice User": [ ]
}
]
},
"put": {
"tags": [
"Relation Type"
],
"operationId": "PutRelationTypeById",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"oneOf": [
{
"$ref": "#/components/schemas/UpdateRelationTypeRequestModel"
}
]
}
},
"text/json": {
"schema": {
"oneOf": [
{
"$ref": "#/components/schemas/UpdateRelationTypeRequestModel"
}
]
}
},
"application/*+json": {
"schema": {
"oneOf": [
{
"$ref": "#/components/schemas/UpdateRelationTypeRequestModel"
}
]
}
}
}
},
"responses": {
"200": {
"description": "Success",
"headers": {
"Umb-Notifications": {
"description": "The list of notifications produced during the request.",
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/NotificationHeaderModel"
},
"nullable": true
}
}
},
"content": {
"application/json": {
"schema": {
"oneOf": [
{
"$ref": "#/components/schemas/RelationTypeResponseModel"
}
]
}
},
"text/json": {
"schema": {
"oneOf": [
{
"$ref": "#/components/schemas/RelationTypeResponseModel"
}
]
}
},
"text/plain": {
"schema": {
"oneOf": [
{
"$ref": "#/components/schemas/RelationTypeResponseModel"
}
]
}
}
}
},
"400": {
"description": "Bad Request",
"headers": {
"Umb-Notifications": {
"description": "The list of notifications produced during the request.",
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/NotificationHeaderModel"
},
"nullable": true
}
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"404": {
"description": "Not Found",
"headers": {
"Umb-Notifications": {
"description": "The list of notifications produced during the request.",
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/NotificationHeaderModel"
},
"nullable": true
}
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"401": {
"description": "The resource is protected and requires an authentication token"
}
},
"security": [
{
"Backoffice User": [ ]
}
]
}
},
"/umbraco/management/api/v1/tree/relation-type/root": {
"get": {
"tags": [
"Relation Type"
],
"operationId": "GetTreeRelationTypeRoot",
"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": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PagedRelationTypeTreeItemResponseModel"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/PagedRelationTypeTreeItemResponseModel"
}
},
"text/plain": {
"schema": {
"$ref": "#/components/schemas/PagedRelationTypeTreeItemResponseModel"
}
}
}
},
"401": {
"description": "The resource is protected and requires an authentication token"
}
},
"security": [
{
"Backoffice User": [ ]
}
]
}
},
"/umbraco/management/api/v1/relation/child-relation/{childId}": {
"get": {
"tags": [
"Relation"
],
"operationId": "GetRelationChildRelationByChildId",
"parameters": [
{
"name": "childId",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "skip",
"in": "query",
"schema": {
"type": "integer",
"format": "int32",
"default": 0
}
},
{
"name": "take",
"in": "query",
"schema": {
"type": "integer",
"format": "int32",
"default": 100
}
},
{
"name": "relationTypeAlias",
"in": "query",
"schema": {
"type": "string",
"default": ""
}
}
],
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PagedRelationResponseModel"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/PagedRelationResponseModel"
}
},
"text/plain": {
"schema": {
"$ref": "#/components/schemas/PagedRelationResponseModel"
}
}
}
},
"401": {
"description": "The resource is protected and requires an authentication token"
}
},
"security": [
{
"Backoffice User": [ ]
}
]
}
},
"/umbraco/management/api/v1/relation/type/{id}": {
@@ -34733,22 +34307,6 @@
],
"additionalProperties": false
},
"CreateRelationTypeRequestModel": {
"type": "object",
"allOf": [
{
"$ref": "#/components/schemas/RelationTypeBaseModel"
}
],
"properties": {
"id": {
"type": "string",
"format": "uuid",
"nullable": true
}
},
"additionalProperties": false
},
"CreateScriptFolderRequestModel": {
"type": "object",
"allOf": [
@@ -39412,7 +38970,7 @@
},
"additionalProperties": false
},
"PagedRelationTypeTreeItemResponseModel": {
"PagedRelationTypeResponseModel": {
"required": [
"items",
"total"
@@ -39428,7 +38986,7 @@
"items": {
"oneOf": [
{
"$ref": "#/components/schemas/RelationTypeTreeItemResponseModel"
"$ref": "#/components/schemas/RelationTypeResponseModel"
}
]
}
@@ -40138,29 +39696,57 @@
},
"additionalProperties": false
},
"RelationResponseModel": {
"RelationReferenceModel": {
"required": [
"childId",
"createDate",
"parentId"
"id"
],
"type": "object",
"properties": {
"parentId": {
"id": {
"type": "string",
"format": "uuid"
},
"parentName": {
"name": {
"type": "string",
"nullable": true
},
"childId": {
}
},
"additionalProperties": false
},
"RelationResponseModel": {
"required": [
"child",
"createDate",
"id",
"parent",
"relationType"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"childName": {
"type": "string",
"nullable": true
"relationType": {
"oneOf": [
{
"$ref": "#/components/schemas/ReferenceByIdModel"
}
]
},
"parent": {
"oneOf": [
{
"$ref": "#/components/schemas/RelationReferenceModel"
}
]
},
"child": {
"oneOf": [
{
"$ref": "#/components/schemas/RelationReferenceModel"
}
]
},
"createDate": {
"type": "string",
@@ -40188,16 +39774,6 @@
"isBidirectional": {
"type": "boolean"
},
"parentObjectType": {
"type": "string",
"format": "uuid",
"nullable": true
},
"childObjectType": {
"type": "string",
"format": "uuid",
"nullable": true
},
"isDependency": {
"type": "boolean"
}
@@ -40223,9 +39799,7 @@
},
"RelationTypeResponseModel": {
"required": [
"id",
"isDeletable",
"path"
"id"
],
"type": "object",
"allOf": [
@@ -40242,19 +39816,20 @@
"type": "string",
"nullable": true
},
"path": {
"minLength": 1,
"type": "string"
},
"isDeletable": {
"type": "boolean"
},
"parentObjectTypeName": {
"type": "string",
"parentObject": {
"oneOf": [
{
"$ref": "#/components/schemas/ObjectTypeResponseModel"
}
],
"nullable": true
},
"childObjectTypeName": {
"type": "string",
"childObject": {
"oneOf": [
{
"$ref": "#/components/schemas/ObjectTypeResponseModel"
}
],
"nullable": true
}
},
@@ -41907,15 +41482,6 @@
],
"additionalProperties": false
},
"UpdateRelationTypeRequestModel": {
"type": "object",
"allOf": [
{
"$ref": "#/components/schemas/RelationTypeBaseModel"
}
],
"additionalProperties": false
},
"UpdateScriptRequestModel": {
"type": "object",
"allOf": [
@@ -42752,4 +42318,4 @@
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
namespace Umbraco.Cms.Api.Management.ViewModels.Relation;
public sealed class RelationReferenceModel
{
public RelationReferenceModel(Guid id)
=> Id = id;
public Guid Id { get; set; }
public string? Name { get; set; }
}

View File

@@ -1,33 +1,37 @@
using System.ComponentModel;
using System.Text.Json.Serialization;
using System.ComponentModel.DataAnnotations;
namespace Umbraco.Cms.Api.Management.ViewModels.Relation;
public class RelationResponseModel
{
/// <summary>
/// Gets or sets the Parent Id of the Relation (Source).
/// </summary>
[ReadOnly(true)]
public Guid ParentId { get; set; }
public RelationResponseModel(ReferenceByIdModel relationType, RelationReferenceModel parent, RelationReferenceModel child)
{
RelationType = relationType;
Parent = parent;
Child = child;
}
public Guid Id { get; set; }
/// <summary>
/// Gets or sets the Parent Name of the relation (Source).
/// Gets or sets the Type of relation
/// </summary>
[ReadOnly(true)]
public string? ParentName { get; set; }
public ReferenceByIdModel RelationType { get; set; }
/// <summary>
/// Gets or sets the Child Id of the Relation (Destination).
/// Gets or sets the Parent of the Relation (Source).
/// </summary>
[ReadOnly(true)]
public Guid ChildId { get; set; }
[Required]
public RelationReferenceModel Parent { get; set; }
/// <summary>
/// Gets or sets the Child Name of the relation (Destination).
/// Gets or sets the Child of the Relation (Destination).
/// </summary>
[ReadOnly(true)]
public string? ChildName { get; set; }
[Required]
public RelationReferenceModel Child { get; set; }
/// <summary>
/// Gets or sets the date when the Relation was created.

View File

@@ -1,6 +0,0 @@
namespace Umbraco.Cms.Api.Management.ViewModels.RelationType;
public class CreateRelationTypeRequestModel : RelationTypeBaseModel
{
public Guid? Id { get; set; }
}

View File

@@ -15,16 +15,6 @@ public class RelationTypeBaseModel
/// </summary>
public bool IsBidirectional { get; set; }
/// <summary>
/// Gets or sets the parent object type ID.
/// </summary>
public Guid? ParentObjectType { get; set; }
/// <summary>
/// Gets or sets the child object type ID.
/// </summary>
public Guid? ChildObjectType { get; set; }
/// <summary>
/// Gets or sets a boolean indicating whether the RelationType should be returned in "Used by"-queries.
/// </summary>

View File

@@ -8,18 +8,13 @@ public class RelationTypeResponseModel : RelationTypeBaseModel
public string? Alias { get; set; }
[Required]
public string Path { get; set; } = string.Empty;
public bool IsDeletable { get; set; }
/// <summary>
/// Gets or sets the Parent's object type.
/// </summary>
public ObjectTypeResponseModel? ParentObject { get; set; }
/// <summary>
/// Gets or sets the Parent's object type name.
/// Gets or sets the Child's object type.
/// </summary>
public string? ParentObjectTypeName { get; set; }
/// <summary>
/// Gets or sets the Child's object type name.
/// </summary>
public string? ChildObjectTypeName { get; set; }
public ObjectTypeResponseModel? ChildObject { get; set; }
}

View File

@@ -1,5 +0,0 @@
namespace Umbraco.Cms.Api.Management.ViewModels.RelationType;
public class UpdateRelationTypeRequestModel : RelationTypeBaseModel
{
}