V14: Member collection view/filter endpoint (#15727)
* Adding missing members policy * Adding a member filter endpoint * Adding response types to user filter endpoint * Adding create multiple to factory * Updating OpenApi.json
This commit is contained in:
committed by
GitHub
parent
638446bd43
commit
5b1fab1165
@@ -0,0 +1,76 @@
|
||||
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.Member;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Services.OperationStatus;
|
||||
|
||||
namespace Umbraco.Cms.Api.Management.Controllers.Member;
|
||||
|
||||
[ApiVersion("1.0")]
|
||||
public class FilterMemberController : MemberControllerBase
|
||||
{
|
||||
private readonly IMemberTypeService _memberTypeService;
|
||||
private readonly IMemberService _memberService;
|
||||
private readonly IMemberPresentationFactory _memberPresentationFactory;
|
||||
|
||||
public FilterMemberController(
|
||||
IMemberTypeService memberTypeService,
|
||||
IMemberService memberService,
|
||||
IMemberPresentationFactory memberPresentationFactory)
|
||||
{
|
||||
_memberTypeService = memberTypeService;
|
||||
_memberService = memberService;
|
||||
_memberPresentationFactory = memberPresentationFactory;
|
||||
}
|
||||
|
||||
[HttpGet("filter")]
|
||||
[MapToApiVersion("1.0")]
|
||||
[ProducesResponseType(typeof(PagedViewModel<MemberResponseModel>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
|
||||
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
|
||||
public async Task<IActionResult> Filter(
|
||||
Guid? memberTypeId = null,
|
||||
string orderBy = "username",
|
||||
Direction orderDirection = Direction.Ascending,
|
||||
string? filter = null,
|
||||
int skip = 0,
|
||||
int take = 100)
|
||||
{
|
||||
// TODO: Move to service once we have FilterAsync method for members
|
||||
string? memberTypeAlias = null;
|
||||
if (memberTypeId.HasValue)
|
||||
{
|
||||
IMemberType? memberType = await _memberTypeService.GetAsync(memberTypeId.Value);
|
||||
if (memberType == null)
|
||||
{
|
||||
return MemberEditingOperationStatusResult(MemberEditingOperationStatus.MemberTypeNotFound);
|
||||
}
|
||||
|
||||
memberTypeAlias = memberType.Alias;
|
||||
}
|
||||
|
||||
PaginationHelper.ConvertSkipTakeToPaging(skip, take, out var pageNumber, out var pageSize);
|
||||
|
||||
IEnumerable<IMember> members = await Task.FromResult(_memberService.GetAll(
|
||||
pageNumber,
|
||||
pageSize,
|
||||
out var totalRecords,
|
||||
orderBy,
|
||||
orderDirection,
|
||||
memberTypeAlias,
|
||||
filter ?? string.Empty));
|
||||
|
||||
var pageViewModel = new PagedViewModel<MemberResponseModel>
|
||||
{
|
||||
Items = await _memberPresentationFactory.CreateMultipleAsync(members),
|
||||
Total = totalRecords,
|
||||
};
|
||||
|
||||
return Ok(pageViewModel);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,15 @@
|
||||
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.User;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.Membership;
|
||||
using Umbraco.Cms.Core.Security;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Services.OperationStatus;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
|
||||
namespace Umbraco.Cms.Api.Management.Controllers.User;
|
||||
|
||||
@@ -42,6 +43,9 @@ public class FilterUserController : UserControllerBase
|
||||
/// <returns>A paged result of the users matching the query.</returns>
|
||||
[HttpGet("filter")]
|
||||
[MapToApiVersion("1.0")]
|
||||
[ProducesResponseType(typeof(PagedViewModel<UserResponseModel>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
|
||||
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
|
||||
public async Task<IActionResult> Filter(
|
||||
int skip = 0,
|
||||
int take = 100,
|
||||
@@ -69,7 +73,7 @@ public class FilterUserController : UserControllerBase
|
||||
var responseModel = new PagedViewModel<UserResponseModel>
|
||||
{
|
||||
Total = filterAttempt.Result.Total,
|
||||
Items = filterAttempt.Result.Items.Select(_userPresentationFactory.CreateResponseModel).ToArray()
|
||||
Items = filterAttempt.Result.Items.Select(_userPresentationFactory.CreateResponseModel).ToArray(),
|
||||
};
|
||||
|
||||
return Ok(responseModel);
|
||||
|
||||
@@ -77,6 +77,7 @@ internal static class BackOfficeAuthPolicyBuilderExtensions
|
||||
AddPolicy(AuthorizationPolicies.SectionAccessForMemberTree, Constants.Security.AllowedApplicationsClaimType,
|
||||
Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members);
|
||||
AddPolicy(AuthorizationPolicies.SectionAccessMedia, Constants.Security.AllowedApplicationsClaimType, Constants.Applications.Media);
|
||||
AddPolicy(AuthorizationPolicies.SectionAccessMembers, Constants.Security.AllowedApplicationsClaimType, Constants.Applications.Members);
|
||||
AddPolicy(AuthorizationPolicies.SectionAccessPackages, Constants.Security.AllowedApplicationsClaimType, Constants.Applications.Packages);
|
||||
AddPolicy(AuthorizationPolicies.SectionAccessSettings, Constants.Security.AllowedApplicationsClaimType, Constants.Applications.Settings);
|
||||
AddPolicy(AuthorizationPolicies.SectionAccessUsers, Constants.Security.AllowedApplicationsClaimType, Constants.Applications.Users);
|
||||
|
||||
@@ -9,7 +9,9 @@ namespace Umbraco.Cms.Api.Management.Factories;
|
||||
|
||||
public interface IMemberPresentationFactory
|
||||
{
|
||||
Task<MemberResponseModel> CreateResponseModelAsync(IMember Member);
|
||||
Task<MemberResponseModel> CreateResponseModelAsync(IMember member);
|
||||
|
||||
Task<IEnumerable<MemberResponseModel>> CreateMultipleAsync(IEnumerable<IMember> members);
|
||||
|
||||
MemberItemResponseModel CreateItemResponseModel(IMemberEntitySlim entity);
|
||||
|
||||
|
||||
@@ -40,6 +40,17 @@ internal sealed class MemberPresentationFactory
|
||||
return responseModel;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<MemberResponseModel>> CreateMultipleAsync(IEnumerable<IMember> members)
|
||||
{
|
||||
var memberResponseModels = new List<MemberResponseModel>();
|
||||
foreach (IMember member in members)
|
||||
{
|
||||
memberResponseModels.Add(await CreateResponseModelAsync(member));
|
||||
}
|
||||
|
||||
return memberResponseModels;
|
||||
}
|
||||
|
||||
public MemberItemResponseModel CreateItemResponseModel(IMemberEntitySlim entity)
|
||||
{
|
||||
var responseModel = new MemberItemResponseModel
|
||||
|
||||
@@ -13316,6 +13316,134 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/umbraco/management/api/v1/member/filter": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Member"
|
||||
],
|
||||
"operationId": "GetMemberFilter",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "memberTypeId",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "orderBy",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"default": "username"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "orderDirection",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/DirectionModel"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "filter",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"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/PagedMemberResponseModel"
|
||||
}
|
||||
},
|
||||
"text/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/PagedMemberResponseModel"
|
||||
}
|
||||
},
|
||||
"text/plain": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/PagedMemberResponseModel"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"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",
|
||||
"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/member/validate": {
|
||||
"post": {
|
||||
"tags": [
|
||||
@@ -23729,7 +23857,64 @@
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success"
|
||||
"description": "Success",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/PagedUserResponseModel"
|
||||
}
|
||||
},
|
||||
"text/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/PagedUserResponseModel"
|
||||
}
|
||||
},
|
||||
"text/plain": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/PagedUserResponseModel"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"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",
|
||||
"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"
|
||||
@@ -29769,6 +29954,30 @@
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"PagedMemberResponseModel": {
|
||||
"required": [
|
||||
"items",
|
||||
"total"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"total": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/MemberResponseModel"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"PagedNamedEntityTreeItemResponseModel": {
|
||||
"required": [
|
||||
"items",
|
||||
|
||||
Reference in New Issue
Block a user