Browse Source

CmsKit - Add EntityType configuration to Comments

pull/7923/head
enisn 5 years ago
parent
commit
b16fc75f29
  1. 51
      modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/CmsKitAdminApplicationModule.cs
  2. 5
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/CmsKitErrorCodes.cs
  3. 3
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json
  4. 1
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json
  5. 11
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/CmsKitCommentOptions.cs
  6. 2
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/Comment.cs
  7. 21
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/CommentEntityTypeDefinition.cs
  8. 42
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/CommentManager.cs
  9. 41
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/DefaultCommentEntityTypeDefinitionStore.cs
  10. 26
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/EntityNotCommentableException.cs
  11. 17
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/ICommentEntityTypeDefinitionStore.cs
  12. 16
      modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Comments/CommentPublicAppService.cs
  13. 59
      modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Comments/CommentManager_Test.cs
  14. 14
      modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs

51
modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/CmsKitAdminApplicationModule.cs

@ -5,6 +5,7 @@ using Volo.Abp.GlobalFeatures;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.CmsKit.Blogs;
using Volo.CmsKit.Comments;
using Volo.CmsKit.GlobalFeatures;
using Volo.CmsKit.Localization;
using Volo.CmsKit.MediaDescriptors;
@ -43,20 +44,20 @@ namespace Volo.CmsKit.Admin
new TagEntityTypeDefiniton(
BlogPostConsts.EntityType,
LocalizableString.Create<CmsKitResource>("BlogPost"),
createPolicies: new[]
createPolicies: new[]
{
CmsKitAdminPermissions.BlogPosts.Create,
CmsKitAdminPermissions.BlogPosts.Update
CmsKitAdminPermissions.BlogPosts.Create,
CmsKitAdminPermissions.BlogPosts.Update
},
updatePolicies: new[]
{
CmsKitAdminPermissions.BlogPosts.Create,
CmsKitAdminPermissions.BlogPosts.Update
updatePolicies: new[]
{
CmsKitAdminPermissions.BlogPosts.Create,
CmsKitAdminPermissions.BlogPosts.Update
},
deletePolicies: new[]
{
CmsKitAdminPermissions.BlogPosts.Create,
CmsKitAdminPermissions.BlogPosts.Update
deletePolicies: new[]
{
CmsKitAdminPermissions.BlogPosts.Create,
CmsKitAdminPermissions.BlogPosts.Update
}));
}
});
@ -70,9 +71,9 @@ namespace Volo.CmsKit.Admin
options.EntityTypes.AddIfNotContains(
new MediaDescriptorDefinition(
BlogPostConsts.EntityType,
createPolicies: new[]
{
CmsKitAdminPermissions.BlogPosts.Create,
createPolicies: new[]
{
CmsKitAdminPermissions.BlogPosts.Create,
CmsKitAdminPermissions.BlogPosts.Update
},
deletePolicies: new[]
@ -88,20 +89,36 @@ namespace Volo.CmsKit.Admin
options.EntityTypes.AddIfNotContains(
new MediaDescriptorDefinition(
PageConsts.EntityType,
createPolicies: new[]
createPolicies: new[]
{
CmsKitAdminPermissions.Pages.Create,
CmsKitAdminPermissions.Pages.Update
CmsKitAdminPermissions.Pages.Update
},
deletePolicies: new[]
{
CmsKitAdminPermissions.Pages.Create,
CmsKitAdminPermissions.Pages.Update,
CmsKitAdminPermissions.Pages.Delete
CmsKitAdminPermissions.Pages.Delete
}));
}
});
}
}
private void ConfigureCommentOptions()
{
if (GlobalFeatureManager.Instance.IsEnabled<CommentsFeature>())
{
Configure<CmsKitCommentOptions>(options =>
{
if (GlobalFeatureManager.Instance.IsEnabled<BlogsFeature>())
{
options.EntityTypes.AddIfNotContains(
new CommentEntityTypeDefinition(BlogPostConsts.EntityType));
}
});
}
}
}
}

5
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/CmsKitErrorCodes.cs

@ -24,6 +24,11 @@
{
public const string SlugAlreadyExist = "CmsKit:BlogPost:0001";
}
public static class Comments
{
public const string EntityNotCommentable = "CmsKit:Comments:0001";
}
public static class MediaDescriptors
{

3
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json

@ -17,10 +17,11 @@
"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:Comments:0001": "The entity {0} is not commentable.",
"CmsKit:Media:0001": "'{Name}' is not a valid media name.",
"CmsKit:Media:0002": "The entity can't have media.",
"CmsKit:Page:0001": "The given url ({0}) already exists.",
"CmsKit:Tag:0002": "The entity is not taggable!",
"CmsKit:Media:0002": "The entity can't have media.",
"CommentAuthorizationExceptionMessage": "Those comments are not allowed for public display.",
"CommentDeletionConfirmationMessage": "This comment and all replies will be deleted!",
"Comments": "Comments",

1
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json

@ -13,6 +13,7 @@
"CmsKit.Ratings": "Puanlama",
"CmsKit.Reactions": "Tepkiler",
"CmsKit.Tags": "Etiketler",
"CmsKit:Comments:0001": "{0} ögesi yorumlanabilir değil.",
"CmsKit:0002": "İçerik zaten mevcut!",
"CmsKit:0003": "{0} ögesi etiketlenebilir değil.",
"CmsKit:BlogPost:0001": "Aynı url etiketi zaten mevcut.",

11
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/CmsKitCommentOptions.cs

@ -0,0 +1,11 @@
using JetBrains.Annotations;
using System.Collections.Generic;
namespace Volo.CmsKit.Comments
{
public class CmsKitCommentOptions
{
[NotNull]
public List<CommentEntityTypeDefinition> EntityTypes { get; } = new List<CommentEntityTypeDefinition>();
}
}

2
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/Comment.cs

@ -28,7 +28,7 @@ namespace Volo.CmsKit.Comments
}
public Comment(
internal Comment(
Guid id,
[NotNull] string entityType,
[NotNull] string entityId,

21
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/CommentEntityTypeDefinition.cs

@ -0,0 +1,21 @@
using JetBrains.Annotations;
using System;
using Volo.Abp;
namespace Volo.CmsKit.Comments
{
public class CommentEntityTypeDefinition : IEquatable<CommentEntityTypeDefinition>
{
public CommentEntityTypeDefinition([NotNull] string entityType)
{
EntityType = Check.NotNullOrEmpty(entityType, nameof(entityType));
}
public string EntityType { get; }
public bool Equals(CommentEntityTypeDefinition other)
{
return EntityType == other?.EntityType;
}
}
}

42
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/CommentManager.cs

@ -0,0 +1,42 @@
using JetBrains.Annotations;
using System;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Domain.Services;
using Volo.CmsKit.Users;
namespace Volo.CmsKit.Comments
{
public class CommentManager : DomainService
{
protected ICommentEntityTypeDefinitionStore DefinitionStore { get; }
public CommentManager(ICommentEntityTypeDefinitionStore definitionStore)
{
DefinitionStore = definitionStore;
}
public virtual async Task<Comment> CreateAsync([NotNull] CmsUser creator,
[NotNull] string entityType,
[NotNull] string entityId,
[NotNull] string text,
[CanBeNull] Guid? repliedCommentId = null)
{
Check.NotNull(creator, nameof(creator));
if (!await DefinitionStore.IsDefinedAsync(entityType))
{
throw new EntityNotCommentableException(entityType);
}
return new Comment(
GuidGenerator.Create(),
entityType,
entityId,
text,
repliedCommentId,
creator.Id,
CurrentTenant.Id);
}
}
}

41
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/DefaultCommentEntityTypeDefinitionStore.cs

@ -0,0 +1,41 @@
using JetBrains.Annotations;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
namespace Volo.CmsKit.Comments
{
public class DefaultCommentEntityTypeDefinitionStore : ICommentEntityTypeDefinitionStore, ITransientDependency
{
protected CmsKitCommentOptions Options { get; }
public DefaultCommentEntityTypeDefinitionStore(IOptions<CmsKitCommentOptions> options)
{
Options = options.Value;
}
public virtual Task<CommentEntityTypeDefinition> GetDefinitionAsync([NotNull] string entityType)
{
Check.NotNullOrWhiteSpace(entityType, nameof(entityType));
var result = Options.EntityTypes.SingleOrDefault(x => x.EntityType.Equals(entityType, StringComparison.InvariantCultureIgnoreCase)) ??
throw new EntityNotCommentableException(entityType);
return Task.FromResult(result);
}
public virtual Task<bool> IsDefinedAsync([NotNull] string entityType)
{
Check.NotNullOrWhiteSpace(entityType, nameof(entityType));
var isDefined = Options.EntityTypes.Any(x => x.EntityType == entityType);
return Task.FromResult(isDefined);
}
}
}

26
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/EntityNotCommentableException.cs

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
namespace Volo.CmsKit.Comments
{
public class EntityNotCommentableException : BusinessException
{
public EntityNotCommentableException(SerializationInfo serializationInfo, StreamingContext context) : base(serializationInfo, context)
{
}
public EntityNotCommentableException(string entityType)
{
Code = CmsKitErrorCodes.Comments.EntityNotCommentable;
EntityType = entityType;
WithData(nameof(EntityType), EntityType);
}
public string EntityType { get; }
}
}

17
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/ICommentEntityTypeDefinitionStore.cs

@ -0,0 +1,17 @@
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.CmsKit.Comments;
namespace Volo.CmsKit.Comments
{
public interface ICommentEntityTypeDefinitionStore
{
Task<CommentEntityTypeDefinition> GetDefinitionAsync([NotNull] string entityType);
Task<bool> IsDefinedAsync([NotNull] string entityType);
}
}

16
modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Comments/CommentPublicAppService.cs

@ -21,20 +21,20 @@ namespace Volo.CmsKit.Public.Comments
protected ICommentRepository CommentRepository { get; }
protected ICmsUserLookupService CmsUserLookupService { get; }
public IDistributedEventBus DistributedEventBus { get; }
public IUnitOfWorkManager UnitOfWorkManager { get; }
protected CommentManager CommentManager { get; }
public CommentPublicAppService(
ICommentRepository commentRepository,
ICmsUserLookupService cmsUserLookupService,
IDistributedEventBus distributedEventBus,
IUnitOfWorkManager unitOfWorkManager,
IOptions<CmsKitOptions> cmsKitOptions)
IOptions<CmsKitOptions> cmsKitOptions,
CommentManager commentManager)
{
CmsKitOptions = cmsKitOptions.Value;
CommentRepository = commentRepository;
CmsUserLookupService = cmsUserLookupService;
DistributedEventBus = distributedEventBus;
UnitOfWorkManager = unitOfWorkManager;
CommentManager = commentManager;
}
public virtual async Task<ListResultDto<CommentWithDetailsDto>> GetListAsync(string entityType, string entityId)
@ -58,14 +58,12 @@ namespace Volo.CmsKit.Public.Comments
}
var comment = await CommentRepository.InsertAsync(
new Comment(
GuidGenerator.Create(),
await CommentManager.CreateAsync(
user,
entityType,
entityId,
input.Text,
input.RepliedCommentId,
user.Id,
CurrentTenant.Id
input.RepliedCommentId
)
);

59
modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Comments/CommentManager_Test.cs

@ -0,0 +1,59 @@
using Shouldly;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.CmsKit.Users;
using Xunit;
namespace Volo.CmsKit.Comments
{
public class CommentManager_Test : CmsKitDomainTestBase
{
private readonly CommentManager commentManager;
private readonly CmsKitTestData testData;
private readonly ICmsUserRepository userRepository;
public CommentManager_Test()
{
commentManager = GetRequiredService<CommentManager>();
testData = GetRequiredService<CmsKitTestData>();
userRepository = GetRequiredService<ICmsUserRepository>();
}
[Fact]
public async Task CreateAsync_ShouldWorkProperly_WithCorrectData()
{
var creator = await userRepository.GetAsync(testData.User1Id);
var text = "Thank you for the article. It's awesome";
var comment = await commentManager.CreateAsync(creator, testData.EntityType1, testData.EntityId1, text);
comment.Id.ShouldNotBe(Guid.Empty);
comment.CreatorId.ShouldBe(creator.Id);
comment.EntityType.ShouldBe(testData.EntityType1);
comment.EntityId.ShouldBe(testData.EntityId1);
comment.Text.ShouldBe(text);
}
[Fact]
public async Task CreateAsync_ShouldThrowException_WithNotConfiguredEntityType()
{
var creator = await userRepository.GetAsync(testData.User1Id);
var notConfiguredEntityType = "Some.New.Entity";
var text = "Thank you for the article. It's awesome";
var exception = await Should.ThrowAsync<EntityNotCommentableException>(async () =>
await commentManager.CreateAsync(
creator,
notConfiguredEntityType,
testData.EntityId1,
text));
exception.ShouldNotBeNull();
exception.EntityType.ShouldBe(notConfiguredEntityType);
}
}
}

14
modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs

@ -45,6 +45,7 @@ namespace Volo.CmsKit
private readonly IBlobContainer<MediaContainer> _mediaBlobContainer;
private readonly BlogManager _blogManager;
private readonly IOptions<CmsKitMediaOptions> _mediaOptions;
private readonly IOptions<CmsKitCommentOptions> _commentsOptions;
public CmsKitDataSeedContributor(
IGuidGenerator guidGenerator,
@ -64,11 +65,12 @@ namespace Volo.CmsKit
IBlogFeatureRepository blogFeatureRepository,
EntityTagManager entityTagManager,
IOptions<CmsKitOptions> options,
IOptions<CmsKitTagOptions> tagOptions,
IMediaDescriptorRepository mediaDescriptorRepository,
IBlobContainer<MediaContainer> mediaBlobContainer,
IOptions<CmsKitTagOptions> tagOptions,
IMediaDescriptorRepository mediaDescriptorRepository,
IBlobContainer<MediaContainer> mediaBlobContainer,
BlogManager blogManager,
IOptions<CmsKitMediaOptions> cmsMediaOptions)
IOptions<CmsKitMediaOptions> cmsMediaOptions,
IOptions<CmsKitCommentOptions> commentsOptions)
{
_guidGenerator = guidGenerator;
_cmsUserRepository = cmsUserRepository;
@ -92,6 +94,7 @@ namespace Volo.CmsKit
_mediaBlobContainer = mediaBlobContainer;
_blogManager = blogManager;
_mediaOptions = cmsMediaOptions;
_commentsOptions = commentsOptions;
}
public async Task SeedAsync(DataSeedContext context)
@ -134,6 +137,9 @@ namespace Volo.CmsKit
createPolicies: new[] { "SomeCreatePolicy" },
deletePolicies: new[] { "SomeDeletePolicy" }));
_commentsOptions.Value.EntityTypes.Add(
new CommentEntityTypeDefinition(_cmsKitTestData.EntityType1));
return Task.CompletedTask;
}

Loading…
Cancel
Save