mirror of https://github.com/abpframework/abp.git
34 changed files with 600 additions and 138 deletions
@ -0,0 +1,21 @@ |
|||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using Volo.Abp.Validation; |
||||
|
using Volo.CmsKit.Contents; |
||||
|
|
||||
|
namespace Volo.CmsKit.Admin.Contents |
||||
|
{ |
||||
|
public class ContentCreateDto |
||||
|
{ |
||||
|
[Required] |
||||
|
[DynamicMaxLength(typeof(ContentConsts), nameof(ContentConsts.MaxEntityTypeLength))] |
||||
|
public string EntityType { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
[DynamicMaxLength(typeof(ContentConsts), nameof(ContentConsts.MaxEntityIdLength))] |
||||
|
public string EntityId { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
[DynamicMaxLength(typeof(ContentConsts), nameof(ContentConsts.MaxValueLength))] |
||||
|
public string Value { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace Volo.CmsKit.Admin.Contents |
||||
|
{ |
||||
|
public class ContentGetListInput : PagedAndSortedResultRequestDto |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using Volo.Abp.Validation; |
||||
|
using Volo.CmsKit.Contents; |
||||
|
|
||||
|
namespace Volo.CmsKit.Admin.Contents |
||||
|
{ |
||||
|
public class ContentUpdateDto |
||||
|
{ |
||||
|
[Required] |
||||
|
[DynamicMaxLength(typeof(ContentConsts), nameof(ContentConsts.MaxValueLength))] |
||||
|
public string Value { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
using Volo.CmsKit.Admin.Contents; |
||||
|
|
||||
|
namespace Volo.CmsKit.Admin.Contents |
||||
|
{ |
||||
|
public interface IContentAdminAppService |
||||
|
: ICrudAppService< |
||||
|
ContentDto, |
||||
|
Guid, |
||||
|
ContentGetListInput, |
||||
|
ContentCreateDto, |
||||
|
ContentUpdateDto> |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,57 @@ |
|||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
using Volo.CmsKit.Contents; |
||||
|
using Volo.CmsKit.Domain.Volo.CmsKit.Contents; |
||||
|
using Volo.CmsKit.Permissions; |
||||
|
|
||||
|
namespace Volo.CmsKit.Admin.Contents |
||||
|
{ |
||||
|
[Authorize(CmsKitAdminPermissions.Contents.Default)] |
||||
|
public class ContentAdminAppService : |
||||
|
CrudAppService< |
||||
|
Content, |
||||
|
ContentDto, |
||||
|
Guid, |
||||
|
ContentGetListInput, |
||||
|
ContentCreateDto, |
||||
|
ContentUpdateDto |
||||
|
>, IContentAdminAppService |
||||
|
{ |
||||
|
protected IContentManager ContentManager { get; } |
||||
|
|
||||
|
protected IContentRepository ContentRepository { get; } |
||||
|
|
||||
|
public ContentAdminAppService( |
||||
|
IRepository<Content, Guid> repository, |
||||
|
IContentManager contentManager, |
||||
|
IContentRepository contentRepository) : base(repository) |
||||
|
{ |
||||
|
ContentManager = contentManager; |
||||
|
|
||||
|
GetListPolicyName = CmsKitAdminPermissions.Contents.Default; |
||||
|
GetPolicyName = CmsKitAdminPermissions.Contents.Default; |
||||
|
CreatePolicyName = CmsKitAdminPermissions.Contents.Create; |
||||
|
UpdatePolicyName = CmsKitAdminPermissions.Contents.Update; |
||||
|
DeletePolicyName = CmsKitAdminPermissions.Contents.Delete; |
||||
|
ContentRepository = contentRepository; |
||||
|
} |
||||
|
|
||||
|
[Authorize(CmsKitAdminPermissions.Contents.Create)] |
||||
|
public override async Task<ContentDto> CreateAsync(ContentCreateDto input) |
||||
|
{ |
||||
|
var entity = new Content( |
||||
|
GuidGenerator.Create(), |
||||
|
input.EntityType, |
||||
|
input.EntityId, |
||||
|
input.Value, |
||||
|
CurrentTenant?.Id); |
||||
|
|
||||
|
await ContentManager.InsertAsync(entity); |
||||
|
|
||||
|
return MapToGetListOutputDto(entity); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,63 @@ |
|||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.GlobalFeatures; |
||||
|
using Volo.CmsKit.Admin.Contents; |
||||
|
using Volo.CmsKit.GlobalFeatures; |
||||
|
using Volo.CmsKit.Permissions; |
||||
|
|
||||
|
namespace Volo.CmsKit.Admin.Contents |
||||
|
{ |
||||
|
[Authorize(CmsKitAdminPermissions.Contents.Default)] |
||||
|
[RequiresGlobalFeature(typeof(ContentsFeature))] |
||||
|
[RemoteService(Name = CmsKitCommonRemoteServiceConsts.RemoteServiceName)] |
||||
|
[Area("cms-kit")] |
||||
|
[Route("api/cms-kit-admin/contents")] |
||||
|
public class ContentAdminController : CmsKitAdminController, IContentAdminAppService |
||||
|
{ |
||||
|
protected IContentAdminAppService ContentAdminAppService { get; } |
||||
|
|
||||
|
public ContentAdminController(IContentAdminAppService contentAdminAppService) |
||||
|
{ |
||||
|
ContentAdminAppService = contentAdminAppService; |
||||
|
} |
||||
|
|
||||
|
[HttpPost] |
||||
|
[Authorize(CmsKitAdminPermissions.Contents.Create)] |
||||
|
public Task<ContentDto> CreateAsync(ContentCreateDto input) |
||||
|
{ |
||||
|
return ContentAdminAppService.CreateAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpDelete("{id}")] |
||||
|
[Authorize(CmsKitAdminPermissions.Contents.Delete)] |
||||
|
public Task DeleteAsync(Guid id) |
||||
|
{ |
||||
|
return ContentAdminAppService.DeleteAsync(id); |
||||
|
} |
||||
|
|
||||
|
[HttpGet("{id}")] |
||||
|
[Authorize(CmsKitAdminPermissions.Contents.Default)] |
||||
|
public Task<ContentDto> GetAsync(Guid id) |
||||
|
{ |
||||
|
return ContentAdminAppService.GetAsync(id); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Authorize(CmsKitAdminPermissions.Contents.Default)] |
||||
|
public Task<PagedResultDto<ContentDto>> GetListAsync(ContentGetListInput input) |
||||
|
{ |
||||
|
return ContentAdminAppService.GetListAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpPut] |
||||
|
[Authorize(CmsKitAdminPermissions.Contents.Update)] |
||||
|
public Task<ContentDto> UpdateAsync(Guid id, ContentUpdateDto input) |
||||
|
{ |
||||
|
return ContentAdminAppService.UpdateAsync(id, input); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,31 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Domain.Services; |
||||
|
using Volo.CmsKit.Contents; |
||||
|
|
||||
|
namespace Volo.CmsKit.Domain.Volo.CmsKit.Contents |
||||
|
{ |
||||
|
public class ContentManager : DomainService, IContentManager |
||||
|
{ |
||||
|
protected IContentRepository ContentRepository { get; } |
||||
|
|
||||
|
public ContentManager(IContentRepository contentRepository) |
||||
|
{ |
||||
|
ContentRepository = contentRepository; |
||||
|
} |
||||
|
|
||||
|
public async Task<Content> InsertAsync(Content content, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
if (await ContentRepository.ExistsAsync(content.EntityType, content.EntityId, content.TenantId, cancellationToken)) |
||||
|
{ |
||||
|
throw new ContentAlreadyExistException(content.EntityType, content.EntityId); |
||||
|
} |
||||
|
|
||||
|
return await ContentRepository.InsertAsync(content); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.CmsKit.Contents; |
||||
|
|
||||
|
namespace Volo.CmsKit.Domain.Volo.CmsKit.Contents |
||||
|
{ |
||||
|
public interface IContentManager |
||||
|
{ |
||||
|
Task<Content> InsertAsync(Content content, CancellationToken cancellationToken = default); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using System; |
||||
|
using Volo.Abp; |
||||
|
|
||||
|
namespace Volo.CmsKit.Contents |
||||
|
{ |
||||
|
[Serializable] |
||||
|
public class ContentAlreadyExistException : BusinessException |
||||
|
{ |
||||
|
public ContentAlreadyExistException([NotNull] string entityType, [NotNull] string entityId) |
||||
|
{ |
||||
|
Code = CmsKitErrorCodes.ContentAlreadyExist; |
||||
|
WithData(nameof(Content.EntityType), entityType); |
||||
|
WithData(nameof(Content.EntityId), entityId); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,13 +0,0 @@ |
|||||
using System.ComponentModel.DataAnnotations; |
|
||||
|
|
||||
namespace Volo.CmsKit.Public.Tags |
|
||||
{ |
|
||||
public class GetRelatedTagsInput |
|
||||
{ |
|
||||
[Required] |
|
||||
public string EntityType { get; set; } |
|
||||
|
|
||||
[Required] |
|
||||
public string EntityId { get; set; } |
|
||||
} |
|
||||
} |
|
||||
@ -1,27 +0,0 @@ |
|||||
using Microsoft.AspNetCore.Mvc; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Threading.Tasks; |
|
||||
using Volo.Abp; |
|
||||
using Volo.CmsKit.Tags; |
|
||||
|
|
||||
namespace Volo.CmsKit.Public.Tags |
|
||||
{ |
|
||||
[RemoteService(Name = CmsKitCommonRemoteServiceConsts.RemoteServiceName)] |
|
||||
[Area("cms-kit")] |
|
||||
[Route("api/cms-kit/tags")] |
|
||||
public class TagController : CmsKitPublicControllerBase, ITagAppService |
|
||||
{ |
|
||||
protected readonly ITagAppService TagAppService; |
|
||||
|
|
||||
public TagController(ITagAppService tagAppService) |
|
||||
{ |
|
||||
TagAppService = tagAppService; |
|
||||
} |
|
||||
|
|
||||
[HttpGet] |
|
||||
public Task<List<TagDto>> GetAllRelatedTagsAsync(GetRelatedTagsInput input) |
|
||||
{ |
|
||||
return TagAppService.GetAllRelatedTagsAsync(input); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,31 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.GlobalFeatures; |
||||
|
using Volo.CmsKit.GlobalFeatures; |
||||
|
using Volo.CmsKit.Tags; |
||||
|
|
||||
|
namespace Volo.CmsKit.Public.Tags |
||||
|
{ |
||||
|
[RequiresGlobalFeature(typeof(TagsFeature))] |
||||
|
[RemoteService(Name = CmsKitCommonRemoteServiceConsts.RemoteServiceName)] |
||||
|
[Area("cms-kit")] |
||||
|
[Route("api/cms-kit-public/tags")] |
||||
|
public class TagPublicController : CmsKitPublicControllerBase, ITagAppService |
||||
|
{ |
||||
|
protected readonly ITagAppService TagAppService; |
||||
|
|
||||
|
public TagPublicController(ITagAppService tagAppService) |
||||
|
{ |
||||
|
TagAppService = tagAppService; |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("{entityType}/{entityId}")] |
||||
|
public Task<List<TagDto>> GetAllRelatedTagsAsync(string entityType, string entityId) |
||||
|
{ |
||||
|
return TagAppService.GetAllRelatedTagsAsync(entityType, entityId); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,129 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using NSubstitute; |
||||
|
using Shouldly; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
using Volo.Abp.Users; |
||||
|
using Volo.CmsKit.Admin.Contents; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Volo.CmsKit.Contents |
||||
|
{ |
||||
|
public class ContentAdminAppService_Tests : CmsKitApplicationTestBase |
||||
|
{ |
||||
|
private ICurrentUser _currentUser; |
||||
|
private readonly CmsKitTestData _data; |
||||
|
private readonly IContentAdminAppService _service; |
||||
|
public ContentAdminAppService_Tests() |
||||
|
{ |
||||
|
_data = GetRequiredService<CmsKitTestData>(); |
||||
|
_service = GetRequiredService<IContentAdminAppService>(); |
||||
|
} |
||||
|
|
||||
|
protected override void AfterAddApplication(IServiceCollection services) |
||||
|
{ |
||||
|
_currentUser = Substitute.For<ICurrentUser>(); |
||||
|
services.AddSingleton(_currentUser); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ShouldGetListAsync() |
||||
|
{ |
||||
|
var result = await _service.GetListAsync(new ContentGetListInput()); |
||||
|
|
||||
|
result.ShouldNotBeNull(); |
||||
|
result.Items.ShouldNotBeEmpty(); |
||||
|
result.Items.Count.ShouldBe(4); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ShouldGetAsync() |
||||
|
{ |
||||
|
var result = await _service.GetAsync(_data.Content_1_Id); |
||||
|
|
||||
|
result.ShouldNotBeNull(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ShouldCreateAsync() |
||||
|
{ |
||||
|
var entityId = "1-2-3"; |
||||
|
var entityType = "My.Awesome.Blog"; |
||||
|
var value = "Some long content"; |
||||
|
|
||||
|
var created = await _service.CreateAsync(new ContentCreateDto |
||||
|
{ |
||||
|
EntityId = entityId, |
||||
|
EntityType = entityType, |
||||
|
Value = value |
||||
|
}); |
||||
|
|
||||
|
created.Id.ShouldNotBe(Guid.Empty); |
||||
|
|
||||
|
var content = await _service.GetAsync(created.Id); |
||||
|
|
||||
|
content.ShouldNotBeNull(); |
||||
|
content.EntityType.ShouldBe(entityType); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ShouldNotCreateWithSameParametersAsync() |
||||
|
{ |
||||
|
var entityTtype = "My.Awesome.Book"; |
||||
|
var entityId = "1"; |
||||
|
|
||||
|
await _service.CreateAsync(new ContentCreateDto |
||||
|
{ |
||||
|
EntityId = entityId, |
||||
|
EntityType = entityTtype, |
||||
|
Value = "Some long content" |
||||
|
}); |
||||
|
|
||||
|
await Should.ThrowAsync<ContentAlreadyExistException>(async () => |
||||
|
await _service.CreateAsync(new ContentCreateDto |
||||
|
{ |
||||
|
EntityId = entityId, |
||||
|
EntityType = entityTtype, |
||||
|
Value = "Yet another long content" |
||||
|
}) |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ShouldUpdateAsync() |
||||
|
{ |
||||
|
string newValue = "Newly created fresh value"; |
||||
|
var updateDto = new ContentUpdateDto |
||||
|
{ |
||||
|
Value = newValue |
||||
|
}; |
||||
|
|
||||
|
await _service.UpdateAsync(_data.Content_1_Id, updateDto); |
||||
|
|
||||
|
var content = await _service.GetAsync(_data.Content_1_Id); |
||||
|
content.ShouldNotBeNull(); |
||||
|
content.Value.ShouldBe(newValue); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ShouldDeleteAsync() |
||||
|
{ |
||||
|
await _service.DeleteAsync(_data.Content_2_Id); |
||||
|
|
||||
|
await Should.ThrowAsync<EntityNotFoundException>(async () => await _service.GetAsync(_data.Content_2_Id)); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ShouldNotThrowEntityNotFoundExceptionWhileDeletingAlreadyDeletedAsync() |
||||
|
{ |
||||
|
await _service.DeleteAsync(_data.Content_2_Id); |
||||
|
|
||||
|
await Should.NotThrowAsync(async () => |
||||
|
await _service.DeleteAsync(_data.Content_2_Id)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue