diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/BlogDto.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/BlogDto.cs index 2e43db655c..e992ae8b1d 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/BlogDto.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/BlogDto.cs @@ -1,20 +1,13 @@ using System; -using System.ComponentModel.DataAnnotations; using Volo.Abp.Application.Dtos; -using Volo.Abp.Validation; -using Volo.CmsKit.Blogs; namespace Volo.CmsKit.Admin.Blogs { [Serializable] public class BlogDto : EntityDto { - [Required] - [DynamicMaxLength(typeof(BlogConsts), nameof(BlogConsts.MaxNameLength))] public string Name { get; set; } - [Required] - [DynamicMaxLength(typeof(BlogConsts), nameof(BlogConsts.MaxSlugLength))] public string Slug { get; set; } } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/CreateBlogDto.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/CreateBlogDto.cs new file mode 100644 index 0000000000..985567b48e --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/CreateBlogDto.cs @@ -0,0 +1,17 @@ +using System.ComponentModel.DataAnnotations; +using Volo.Abp.Validation; +using Volo.CmsKit.Blogs; + +namespace Volo.CmsKit.Admin.Blogs +{ + public class CreateBlogDto + { + [Required] + [DynamicMaxLength(typeof(BlogConsts), nameof(BlogConsts.MaxNameLength))] + public string Name { get; set; } + + [Required] + [DynamicMaxLength(typeof(BlogConsts), nameof(BlogConsts.MaxSlugLength))] + public string Slug { get; set; } + } +} \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogAdminAppService.cs index 3544b3d7af..6d82e6117c 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogAdminAppService.cs @@ -3,7 +3,7 @@ using Volo.Abp.Application.Services; namespace Volo.CmsKit.Admin.Blogs { - public interface IBlogAdminAppService : ICrudAppService + public interface IBlogAdminAppService : ICrudAppService { } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/UpdateBlogDto.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/UpdateBlogDto.cs new file mode 100644 index 0000000000..832c1b7214 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/UpdateBlogDto.cs @@ -0,0 +1,17 @@ +using System.ComponentModel.DataAnnotations; +using Volo.Abp.Validation; +using Volo.CmsKit.Blogs; + +namespace Volo.CmsKit.Admin.Blogs +{ + public class UpdateBlogDto + { + [Required] + [DynamicMaxLength(typeof(BlogConsts), nameof(BlogConsts.MaxNameLength))] + public string Name { get; set; } + + [Required] + [DynamicMaxLength(typeof(BlogConsts), nameof(BlogConsts.MaxSlugLength))] + public string Slug { get; set; } + } +} \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Blogs/BlogAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Blogs/BlogAdminAppService.cs index 5c833f5256..574f6f737a 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Blogs/BlogAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Blogs/BlogAdminAppService.cs @@ -1,10 +1,8 @@ using Microsoft.AspNetCore.Authorization; using System; using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; -using Volo.Abp.Application.Services; -using Volo.Abp.Domain.Repositories; +using Volo.Abp.Application.Dtos; using Volo.Abp.GlobalFeatures; using Volo.CmsKit.Blogs; using Volo.CmsKit.GlobalFeatures; @@ -14,24 +12,63 @@ namespace Volo.CmsKit.Admin.Blogs { [RequiresGlobalFeature(typeof(BlogsFeature))] [Authorize(CmsKitAdminPermissions.Blogs.Default)] - public class BlogAdminAppService : CrudAppService, IBlogAdminAppService + public class BlogAdminAppService : CmsKitAdminAppServiceBase, IBlogAdminAppService { - public BlogAdminAppService(IRepository repository) : base(repository) + protected IBlogRepository BlogRepository { get; } + protected BlogManager BlogManager { get; } + + public BlogAdminAppService(IBlogRepository blogRepository, BlogManager blogManager) { - GetListPolicyName = CmsKitAdminPermissions.Blogs.Default; - GetPolicyName = CmsKitAdminPermissions.Blogs.Default; - CreatePolicyName = CmsKitAdminPermissions.Blogs.Create; - UpdatePolicyName = CmsKitAdminPermissions.Blogs.Update; - DeletePolicyName = CmsKitAdminPermissions.Blogs.Delete; + BlogRepository = blogRepository; + BlogManager = blogManager; + } + + public virtual async Task GetAsync(Guid id) + { + var blog = await BlogRepository.GetAsync(id); + + return ObjectMapper.Map(blog); + } + + public virtual async Task> GetListAsync(BlogGetListInput input) + { + var totalCount = await BlogRepository.GetCountAsync(input.Filter); + + var blogs = await BlogRepository.GetListAsync( + input.Filter, + input.Sorting, + input.MaxResultCount, + input.SkipCount); + + return new PagedResultDto(totalCount, ObjectMapper.Map, List>(blogs)); + } + + [Authorize(CmsKitAdminPermissions.Blogs.Create)] + public virtual async Task CreateAsync(CreateBlogDto input) + { + var blog = await BlogManager.CreateAsync(input.Name, input.Slug); + + await BlogRepository.InsertAsync(blog); + + return ObjectMapper.Map(blog); + } + + [Authorize(CmsKitAdminPermissions.Blogs.Update)] + public virtual async Task UpdateAsync(Guid id, UpdateBlogDto input) + { + var blog = await BlogRepository.GetAsync(id); + + blog = await BlogManager.UpdateAsync(blog, input.Name, input.Slug); + + await BlogRepository.UpdateAsync(blog); + + return ObjectMapper.Map(blog); } - protected override async Task> CreateFilteredQueryAsync(BlogGetListInput input) + [Authorize(CmsKitAdminPermissions.Blogs.Delete)] + public virtual Task DeleteAsync(Guid id) { - var queryable = await base.CreateFilteredQueryAsync(input); - return queryable - .WhereIf( - !input.Filter.IsNullOrWhiteSpace(), - x => x.Name.ToLower().Contains(input.Filter)); + return BlogRepository.DeleteAsync(id); } } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/CmsKitAdminApplicationAutoMapperProfile.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/CmsKitAdminApplicationAutoMapperProfile.cs index be14293134..13c36ee42a 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/CmsKitAdminApplicationAutoMapperProfile.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/CmsKitAdminApplicationAutoMapperProfile.cs @@ -37,8 +37,7 @@ namespace Volo.CmsKit.Admin CreateMap(MemberList.Source); CreateMap(MemberList.Source); - CreateMap(MemberList.Destination) - .ReverseMap(); + CreateMap(); CreateMap(); diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogAdminController.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogAdminController.cs index da565413b1..5e8067ed6f 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogAdminController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogAdminController.cs @@ -1,9 +1,6 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; using Volo.Abp; using Volo.Abp.Application.Dtos; @@ -27,42 +24,40 @@ namespace Volo.CmsKit.Admin.Blogs BlogAdminAppService = blogAdminAppService; } - [HttpPost] - [Authorize(CmsKitAdminPermissions.Blogs.Create)] - public Task CreateAsync(BlogDto input) - { - return BlogAdminAppService.CreateAsync(input); - } - - [HttpDelete] - [Route("{id}")] - [Authorize(CmsKitAdminPermissions.Blogs.Delete)] - public Task DeleteAsync(Guid id) - { - return BlogAdminAppService.DeleteAsync(id); - } - [HttpGet] [Route("{id}")] - [Authorize(CmsKitAdminPermissions.Blogs.Default)] public Task GetAsync(Guid id) { return BlogAdminAppService.GetAsync(id); } [HttpGet] - [Authorize(CmsKitAdminPermissions.Blogs.Default)] - public Task> GetListAsync([FromQuery] BlogGetListInput input) + public Task> GetListAsync(BlogGetListInput input) { return BlogAdminAppService.GetListAsync(input); } + + [HttpPost] + [Authorize(CmsKitAdminPermissions.Blogs.Create)] + public Task CreateAsync(CreateBlogDto input) + { + return BlogAdminAppService.CreateAsync(input); + } [HttpPut] [Route("{id}")] [Authorize(CmsKitAdminPermissions.Blogs.Update)] - public Task UpdateAsync(Guid id, BlogDto input) + public Task UpdateAsync(Guid id, UpdateBlogDto input) { return BlogAdminAppService.UpdateAsync(id, input); } + + [HttpDelete] + [Route("{id}")] + [Authorize(CmsKitAdminPermissions.Blogs.Delete)] + public Task DeleteAsync(Guid id) + { + return BlogAdminAppService.DeleteAsync(id); + } } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/CmsKitErrorCodes.cs b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/CmsKitErrorCodes.cs index 3251bcb230..64956b8683 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/CmsKitErrorCodes.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/CmsKitErrorCodes.cs @@ -16,6 +16,11 @@ } public static class Blogs + { + public const string SlugAlreadyExists = "CmsKit:Blog:0001"; + } + + public static class BlogPosts { public const string SlugAlreadyExist = "CmsKit:BlogPost:0001"; } diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json index 45e2e56a9b..212d495459 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json @@ -3,6 +3,7 @@ "texts": { "CmsKit:0002": "Content already exists!", "CmsKit:0003": "The entity {0} is not taggable.", + "CmsKit:Blog:0001": "The given slug ({Slug}) already exists!", "CmsKit:BlogPost:0001": "The given slug already exists!", "CmsKit:Media:0001": "'{Name}' is not a valid media name.", "CmsKit:Page:0001": "The given url ({0}) already exists.", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/Blog.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/Blog.cs index 832ed4385e..313b282a1f 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/Blog.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/Blog.cs @@ -9,17 +9,6 @@ namespace Volo.CmsKit.Blogs { public class Blog : FullAuditedAggregateRoot, IMultiTenant { - public Blog( - Guid id, - [NotNull] string name, - [NotNull] string slug, - [CanBeNull] Guid? tenantId = null) : base(id) - { - SetName(name); - SetSlug(slug); - TenantId = tenantId; - } - [NotNull] public virtual string Name { get; protected set; } @@ -27,15 +16,22 @@ namespace Volo.CmsKit.Blogs public virtual string Slug { get; protected set; } public virtual Guid? TenantId { get; protected set; } - + + protected internal Blog(Guid id, [NotNull] string name, [NotNull] string slug, [CanBeNull] Guid? tenantId = null) : base(id) + { + SetName(name); + SetSlug(slug); + TenantId = tenantId; + } + public virtual void SetName(string name) { - Name = Check.NotNullOrWhiteSpace(name, nameof(name), maxLength: BlogConsts.MaxNameLength); + Name = Check.NotNullOrWhiteSpace(name, nameof(name), BlogConsts.MaxNameLength); } public virtual void SetSlug(string slug) { - Check.NotNullOrWhiteSpace(slug, nameof(slug), maxLength: BlogConsts.MaxNameLength); + Check.NotNullOrWhiteSpace(slug, nameof(slug), BlogConsts.MaxNameLength); Slug = slug.NormalizeSlug(); } diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogManager.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogManager.cs new file mode 100644 index 0000000000..1d2e2f5b07 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogManager.cs @@ -0,0 +1,44 @@ +using System.Threading.Tasks; +using JetBrains.Annotations; +using Volo.Abp.Domain.Services; + +namespace Volo.CmsKit.Blogs +{ + public class BlogManager : DomainService + { + protected IBlogRepository BlogRepository { get; } + + public BlogManager(IBlogRepository blogRepository) + { + BlogRepository = blogRepository; + } + + public virtual async Task CreateAsync([NotNull] string name, [NotNull] string slug) + { + await CheckSlugAsync(slug); + + return new Blog(GuidGenerator.Create(), name, slug, CurrentTenant.Id); + } + + public virtual async Task UpdateAsync([NotNull] Blog blog, [NotNull] string name, [NotNull] string slug) + { + if (slug != blog.Slug) + { + await CheckSlugAsync(slug); + } + + blog.SetName(name); + blog.SetSlug(slug); + + return blog; + } + + protected virtual async Task CheckSlugAsync([NotNull] string slug) + { + if (await BlogRepository.SlugExistsAsync(slug)) + { + throw new BlogSlugAlreadyExistException(slug); + } + } + } +} \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPostSlugAlreadyExistException.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPostSlugAlreadyExistException.cs index 034cb8e60d..a2cdf68f39 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPostSlugAlreadyExistException.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPostSlugAlreadyExistException.cs @@ -19,7 +19,7 @@ namespace Volo.CmsKit.Blogs Slug = slug; BlogId = blogId; - Code = CmsKitErrorCodes.Blogs.SlugAlreadyExist; + Code = CmsKitErrorCodes.BlogPosts.SlugAlreadyExist; WithData(nameof(Slug), Slug); WithData(nameof(BlogId), BlogId); diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogSlugAlreadyExistException.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogSlugAlreadyExistException.cs new file mode 100644 index 0000000000..e50f2f623c --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogSlugAlreadyExistException.cs @@ -0,0 +1,22 @@ +using System; +using System.Runtime.Serialization; +using Volo.Abp; + +namespace Volo.CmsKit.Blogs +{ + [Serializable] + public class BlogSlugAlreadyExistException : BusinessException + { + public BlogSlugAlreadyExistException(string slug) + { + Code = CmsKitErrorCodes.Blogs.SlugAlreadyExists; + + WithData(nameof(Blog.Slug), slug); + } + + public BlogSlugAlreadyExistException( + SerializationInfo serializationInfo, StreamingContext context) : base(serializationInfo, context) + { + } + } +} diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/IBlogRepository.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/IBlogRepository.cs index 2feb057111..b340b9e256 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/IBlogRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/IBlogRepository.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Volo.Abp.Domain.Repositories; @@ -7,7 +8,23 @@ namespace Volo.CmsKit.Blogs { public interface IBlogRepository : IBasicRepository { - public Task GetBySlugAsync(string slug, CancellationToken cancellationToken = default); - Task ExistsAsync(Guid blogId, CancellationToken cancellationToken = default); + Task> GetListAsync( + string filter = null, + string sorting = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, + CancellationToken cancellationToken = default + ); + + Task GetCountAsync( + string filter = null, + CancellationToken cancellationToken = default + ); + + Task GetBySlugAsync(string slug, CancellationToken cancellationToken = default); + + Task ExistsAsync(Guid id, CancellationToken cancellationToken = default); + + Task SlugExistsAsync(string slug, CancellationToken cancellationToken = default); } } diff --git a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Blogs/EfCoreBlogRepository.cs b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Blogs/EfCoreBlogRepository.cs index c39dee2685..bfcb6d3cab 100644 --- a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Blogs/EfCoreBlogRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Blogs/EfCoreBlogRepository.cs @@ -1,9 +1,11 @@ -using Microsoft.EntityFrameworkCore; -using System; -using System.Security.Cryptography.X509Certificates; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Dynamic.Core; using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; using Volo.Abp; using Volo.Abp.Domain.Repositories.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore; @@ -17,15 +19,47 @@ namespace Volo.CmsKit.Blogs { } - public virtual async Task ExistsAsync(Guid blogId, CancellationToken cancellationToken = default) + public virtual async Task ExistsAsync(Guid id, CancellationToken cancellationToken = default) { - return await (await GetQueryableAsync()).AnyAsync(x => x.Id == blogId, GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync()).AnyAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); } - public virtual Task GetBySlugAsync([NotNull]string slug, CancellationToken cancellationToken = default) + public virtual async Task SlugExistsAsync(string slug, CancellationToken cancellationToken = default) + { + return await (await GetDbSetAsync()).AnyAsync(x => x.Slug == slug, GetCancellationToken(cancellationToken)); + } + + public virtual async Task> GetListAsync( + string filter = null, + string sorting = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, + CancellationToken cancellationToken = default) + { + var query = await GetListQueryAsync(filter); + + return await query.OrderBy(sorting ?? "creationTime desc") + .PageBy(skipCount, maxResultCount) + .ToListAsync(GetCancellationToken(cancellationToken)); + } + + public virtual async Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) + { + var query = await GetListQueryAsync(filter); + + return await query.LongCountAsync(GetCancellationToken(cancellationToken)); + } + + public virtual Task GetBySlugAsync([NotNull] string slug, CancellationToken cancellationToken = default) { Check.NotNullOrEmpty(slug, nameof(slug)); return GetAsync(x => x.Slug == slug, cancellationToken: GetCancellationToken(cancellationToken)); } + + protected virtual async Task> GetListQueryAsync(string filter = null) + { + return (await GetDbSetAsync()) + .WhereIf(!filter.IsNullOrWhiteSpace(), b => b.Name.Contains(filter)); + } } } diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogRepository.cs index 0cd46a130c..32119610bb 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogRepository.cs @@ -1,8 +1,12 @@ -using MongoDB.Driver.Core.Operations; -using System; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Dynamic.Core; using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; +using MongoDB.Driver; +using MongoDB.Driver.Linq; using Volo.Abp; using Volo.Abp.Domain.Repositories.MongoDB; using Volo.Abp.MongoDB; @@ -16,18 +20,54 @@ namespace Volo.CmsKit.MongoDB.Blogs { } - public virtual async Task ExistsAsync(Guid blogId, CancellationToken cancellationToken = default) + public virtual async Task ExistsAsync(Guid id, CancellationToken cancellationToken = default) { - return await AsyncExecuter.AnyAsync( - await GetQueryableAsync(), - x => x.Id == blogId, - cancellationToken); + var token = GetCancellationToken(cancellationToken); + return await (await GetMongoQueryableAsync(token)).AnyAsync(x => x.Id == id, token); } - public virtual Task GetBySlugAsync([NotNull]string slug, CancellationToken cancellationToken = default) + public virtual async Task SlugExistsAsync(string slug, CancellationToken cancellationToken = default) + { + var token = GetCancellationToken(cancellationToken); + return await (await GetMongoQueryableAsync(token)).AnyAsync(x => x.Slug == slug, token); + } + + public virtual async Task> GetListAsync( + string filter = null, + string sorting = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, + CancellationToken cancellationToken = default) + { + var token = GetCancellationToken(cancellationToken); + + var query = await GetListQueryAsync(filter, token); + + return await query.OrderBy(sorting ?? "creationTime desc") + .As>() + .PageBy>(skipCount, maxResultCount) + .ToListAsync(token); + } + + public virtual async Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) + { + var token = GetCancellationToken(cancellationToken); + + var query = await GetListQueryAsync(filter, token); + + return await query.As>().LongCountAsync(token); + } + + public virtual Task GetBySlugAsync([NotNull] string slug, CancellationToken cancellationToken = default) { Check.NotNullOrEmpty(slug, nameof(slug)); return GetAsync(x => x.Slug == slug, cancellationToken: cancellationToken); } + + protected virtual async Task> GetListQueryAsync(string filter = null, CancellationToken cancellationToken = default) + { + return (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) + .WhereIf(!filter.IsNullOrWhiteSpace(), b => b.Name.Contains(filter)); + } } } diff --git a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Blogs/BlogAdminAppService_Tests.cs b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Blogs/BlogAdminAppService_Tests.cs new file mode 100644 index 0000000000..0f0e4ee2f8 --- /dev/null +++ b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Blogs/BlogAdminAppService_Tests.cs @@ -0,0 +1,92 @@ +using System.Linq; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Domain.Entities; +using Volo.CmsKit.Admin.Blogs; +using Xunit; + +namespace Volo.CmsKit.Blogs +{ + public class BlogAdminAppService_Tests : CmsKitApplicationTestBase + { + protected IBlogAdminAppService BlogAdminAppService { get; } + protected CmsKitTestData CmsKitTestData { get; } + protected IBlogRepository BlogRepository { get; } + + public BlogAdminAppService_Tests() + { + BlogAdminAppService = GetRequiredService(); + CmsKitTestData = GetRequiredService(); + BlogRepository = GetRequiredService(); + } + + [Fact] + public async Task GetAsync() + { + var blog = await BlogAdminAppService.GetAsync(CmsKitTestData.Blog_Id); + + blog.Slug.ShouldBe(CmsKitTestData.BlogSlug); + } + + [Fact] + public async Task GetListAsync() + { + var blogs = await BlogAdminAppService.GetListAsync(new BlogGetListInput()); + + blogs.TotalCount.ShouldBeGreaterThan(0); + blogs.Items.Any(x => x.Slug == CmsKitTestData.BlogSlug).ShouldBeTrue(); + } + + [Fact] + public async Task CreateAsync_ShouldWork() + { + var blog = await BlogAdminAppService.CreateAsync(new CreateBlogDto + { + Name = "News", + Slug = "latest-news" + }); + + blog.ShouldNotBeNull(); + blog.Name.ShouldBe("News"); + blog.Slug.ShouldBe("latest-news"); + } + + [Fact] + public async Task CreateAsync_ShouldThrow_WithExistSlug() + { + await Should.ThrowAsync( + async () => + await BlogAdminAppService.CreateAsync(new CreateBlogDto + { + Name = "News", + Slug = CmsKitTestData.BlogSlug + })); + } + + [Fact] + public async Task UpdateAsync_ShouldWork() + { + var blog = await BlogAdminAppService.UpdateAsync(CmsKitTestData.Blog_Id, new UpdateBlogDto + { + Name = "New Name", + Slug = "new-slug" + }); + + var updatedBlog = await BlogAdminAppService.GetAsync(CmsKitTestData.Blog_Id); + + updatedBlog.Name.ShouldBe("New Name"); + updatedBlog.Slug.ShouldBe("new-slug"); + } + + [Fact] + public async Task DeleteAsync_ShouldWork() + { + await BlogAdminAppService.DeleteAsync(CmsKitTestData.Blog_Id); + + await Should.ThrowAsync( + async () => + await BlogAdminAppService.GetAsync(CmsKitTestData.Blog_Id) + ); + } + } +} \ No newline at end of file diff --git a/modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Blogs/BlogManager_Test.cs b/modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Blogs/BlogManager_Test.cs new file mode 100644 index 0000000000..a5b878d454 --- /dev/null +++ b/modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Blogs/BlogManager_Test.cs @@ -0,0 +1,50 @@ +using System; +using System.Threading.Tasks; +using Shouldly; +using Xunit; + +namespace Volo.CmsKit.Blogs +{ + public class BlogManager_Test : CmsKitDomainTestBase + { + protected IBlogRepository BlogRepository { get; } + protected BlogManager BlogManager { get; } + protected CmsKitTestData TestData { get; } + + public BlogManager_Test() + { + BlogRepository = GetRequiredService(); + BlogManager = GetRequiredService(); + TestData = GetRequiredService(); + } + + [Fact] + public async Task BlogCreate_ShouldThrowException_WithExistSlug() + { + await Should.ThrowAsync( + async () => + await BlogManager.CreateAsync("test-name", TestData.BlogSlug) + ); + } + + [Fact] + public async Task BlogCreate_ShouldWorkProperly() + { + var blog = await BlogManager.CreateAsync("test-name", "test-slug"); + + blog.ShouldNotBeNull(); + blog.Id.ShouldNotBe(Guid.Empty); + } + + [Fact] + public async Task BlogUpdate_ShouldWork() + { + var blog = await BlogRepository.GetAsync(TestData.Blog_Id); + + await BlogManager.UpdateAsync(blog, "New name", "new-slug"); + + blog.Name.ShouldBe("New name"); + blog.Slug.ShouldBe("new-slug"); + } + } +} \ No newline at end of file diff --git a/modules/cms-kit/test/Volo.CmsKit.TestBase/Blogs/BlogRepository_Test.cs b/modules/cms-kit/test/Volo.CmsKit.TestBase/Blogs/BlogRepository_Test.cs index 50a99519eb..6d4fcd59fd 100644 --- a/modules/cms-kit/test/Volo.CmsKit.TestBase/Blogs/BlogRepository_Test.cs +++ b/modules/cms-kit/test/Volo.CmsKit.TestBase/Blogs/BlogRepository_Test.cs @@ -61,5 +61,32 @@ namespace Volo.CmsKit.Blogs result.ShouldBeFalse(); } + + [Fact] + public async Task GetList_ShouldWorkProperly() + { + var list = await blogRepository.GetListAsync(); + + list.ShouldNotBeNull(); + list.Count.ShouldBeGreaterThan(0); + } + + [Fact] + public async Task GetCount_ShouldWorkProperly() + { + var count = await blogRepository.GetCountAsync(); + + count.ShouldBeGreaterThan(0); + } + + [Fact] + public async Task SlugExistAsync_ShouldWorkProperly() + { + var exists = await blogRepository.SlugExistsAsync(testData.BlogSlug); + var notExists = await blogRepository.SlugExistsAsync("not-existing-blog-slug"); + + exists.ShouldBeTrue(); + notExists.ShouldBeFalse(); + } } } diff --git a/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs b/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs index 788b428d69..fbea8e6c47 100644 --- a/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs +++ b/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs @@ -45,6 +45,7 @@ namespace Volo.CmsKit private readonly IOptions _tagOptions; private readonly IMediaDescriptorRepository _mediaDescriptorRepository; private readonly IBlobContainer _mediaBlobContainer; + private readonly BlogManager _blogManager; public CmsKitDataSeedContributor( IGuidGenerator guidGenerator, @@ -65,7 +66,8 @@ namespace Volo.CmsKit IOptions options, IOptions tagOptions, IMediaDescriptorRepository mediaDescriptorRepository, - IBlobContainer mediaBlobContainer) + IBlobContainer mediaBlobContainer, + BlogManager blogManager) { _guidGenerator = guidGenerator; _cmsUserRepository = cmsUserRepository; @@ -86,6 +88,7 @@ namespace Volo.CmsKit _tagOptions = tagOptions; _mediaDescriptorRepository = mediaDescriptorRepository; _mediaBlobContainer = mediaBlobContainer; + _blogManager = blogManager; } public async Task SeedAsync(DataSeedContext context) @@ -325,8 +328,12 @@ namespace Volo.CmsKit private async Task SeedBlogsAsync() { - var blog = await _blogRepository.InsertAsync(new Blog(_cmsKitTestData.Blog_Id, _cmsKitTestData.BlogName, _cmsKitTestData.BlogSlug)); + var blog = await _blogManager.CreateAsync(_cmsKitTestData.BlogName, _cmsKitTestData.BlogSlug); + + await _blogRepository.InsertAsync(blog); + _cmsKitTestData.Blog_Id = blog.Id; + await _blogPostRepository.InsertAsync(new BlogPost(_cmsKitTestData.BlogPost_1_Id, blog.Id, _cmsKitTestData.BlogPost_1_Title, _cmsKitTestData.BlogPost_1_Slug, "Short desc 1")); await _blogPostRepository.InsertAsync(new BlogPost(_cmsKitTestData.BlogPost_2_Id, blog.Id, _cmsKitTestData.BlogPost_2_Title, _cmsKitTestData.BlogPost_2_Slug, "Short desc 2")); diff --git a/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitTestData.cs b/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitTestData.cs index d6a1aad24e..8f62ee3ccd 100644 --- a/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitTestData.cs +++ b/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitTestData.cs @@ -73,7 +73,7 @@ namespace Volo.CmsKit public string TagName_2 => "News"; - public Guid Blog_Id { get; } = Guid.NewGuid(); + public Guid Blog_Id { get; set; } = Guid.NewGuid(); public string BlogName => "Cms Blog";