mirror of https://github.com/abpframework/abp.git
86 changed files with 1412 additions and 447 deletions
|
After Width: | Height: | Size: 6.0 KiB |
|
After Width: | Height: | Size: 7.4 KiB |
@ -0,0 +1,78 @@ |
|||||
|
using System; |
||||
|
using System.IO; |
||||
|
using System.Linq; |
||||
|
using Volo.Abp.Cli.Commands; |
||||
|
|
||||
|
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps |
||||
|
{ |
||||
|
public class MicroserviceServiceRandomPortStep : ProjectBuildPipelineStep |
||||
|
{ |
||||
|
private readonly string _defaultPort = string.Empty; |
||||
|
private string _tyeFileContent = null; |
||||
|
|
||||
|
public MicroserviceServiceRandomPortStep(string defaultPort) |
||||
|
{ |
||||
|
_defaultPort = defaultPort; |
||||
|
} |
||||
|
|
||||
|
public override void Execute(ProjectBuildContext context) |
||||
|
{ |
||||
|
var newPort = GetNewRandomPort(context); |
||||
|
|
||||
|
var targetFiles = context.Files.Where(f=> f.Name.EndsWith("launchSettings.json") || f.Name.EndsWith("appsettings.json")).ToList(); |
||||
|
|
||||
|
foreach (var file in targetFiles) |
||||
|
{ |
||||
|
file.SetContent(file.Content.Replace(_defaultPort, newPort)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private string GetNewRandomPort(ProjectBuildContext context) |
||||
|
{ |
||||
|
string newPort; |
||||
|
var rnd = new Random(); |
||||
|
var tryCount = 0; |
||||
|
|
||||
|
do |
||||
|
{ |
||||
|
newPort = rnd.Next(44350, 45350).ToString(); |
||||
|
|
||||
|
if (tryCount++ > 2000) |
||||
|
{ |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
} while (PortExistsForAnotherService(context, newPort)); |
||||
|
|
||||
|
return newPort; |
||||
|
} |
||||
|
|
||||
|
private bool PortExistsForAnotherService(ProjectBuildContext context, string newPort) |
||||
|
{ |
||||
|
return ReadTyeFileContent(context).SplitToLines().Any(l => l.Contains("port") && l.Contains(newPort)); |
||||
|
} |
||||
|
|
||||
|
private string ReadTyeFileContent(ProjectBuildContext context) |
||||
|
{ |
||||
|
if (_tyeFileContent != null) |
||||
|
{ |
||||
|
return _tyeFileContent; |
||||
|
} |
||||
|
|
||||
|
var solutionFolderPath = context.BuildArgs.ExtraProperties[NewCommand.Options.OutputFolder.Short] ?? |
||||
|
context.BuildArgs.ExtraProperties[NewCommand.Options.OutputFolder.Long] ?? |
||||
|
Directory.GetCurrentDirectory(); |
||||
|
|
||||
|
var tyeFilePath = Path.Combine(solutionFolderPath, "tye.yaml"); |
||||
|
|
||||
|
if (!File.Exists(tyeFilePath)) |
||||
|
{ |
||||
|
return String.Empty; |
||||
|
} |
||||
|
|
||||
|
_tyeFileContent = File.ReadAllText(tyeFilePath); |
||||
|
|
||||
|
return _tyeFileContent; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,54 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
|
||||
|
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps |
||||
|
{ |
||||
|
public class RemoveProjectFromTyeStep : ProjectBuildPipelineStep |
||||
|
{ |
||||
|
private readonly string _name; |
||||
|
|
||||
|
public RemoveProjectFromTyeStep(string name) |
||||
|
{ |
||||
|
_name = name; |
||||
|
} |
||||
|
|
||||
|
public override void Execute(ProjectBuildContext context) |
||||
|
{ |
||||
|
var tyeFile = context.Files.FirstOrDefault(f => f.Name == "/tye.yaml"); |
||||
|
|
||||
|
if (tyeFile == null) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
var lines = tyeFile.GetLines(); |
||||
|
var newLines = new List<string>(); |
||||
|
|
||||
|
var nameLine = $"- name:"; |
||||
|
var isOneOfTargetLines = false; |
||||
|
|
||||
|
foreach (var line in lines) |
||||
|
{ |
||||
|
if (line.Equals($"{nameLine} {_name}")) |
||||
|
{ |
||||
|
isOneOfTargetLines = true; |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
if (line.StartsWith(nameLine)) |
||||
|
{ |
||||
|
isOneOfTargetLines = false; |
||||
|
} |
||||
|
|
||||
|
if (!isOneOfTargetLines) |
||||
|
{ |
||||
|
newLines.Add(line); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
tyeFile.SetContent(String.Join(Environment.NewLine, newLines)); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using Microsoft.Extensions.Logging; |
||||
|
using Volo.Abp.Logging; |
||||
|
|
||||
|
namespace Microsoft.Extensions.DependencyInjection |
||||
|
{ |
||||
|
public static class ServiceCollectionLoggingExtensions |
||||
|
{ |
||||
|
public static ILogger<T> GetInitLogger<T>(this IServiceCollection services) |
||||
|
{ |
||||
|
return services.GetSingletonInstance<IInitLoggerFactory>().Create<T>(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
using System; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
|
||||
|
namespace Volo.Abp.Logging |
||||
|
{ |
||||
|
public class AbpInitLogEntry |
||||
|
{ |
||||
|
public LogLevel LogLevel { get; set; } |
||||
|
|
||||
|
public EventId EventId { get; set; } |
||||
|
|
||||
|
public object State { get; set; } |
||||
|
|
||||
|
public Exception Exception { get; set; } |
||||
|
|
||||
|
public Func<object, Exception, string> Formatter { get; set; } |
||||
|
|
||||
|
public string Message => Formatter(State, Exception); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,38 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
|
||||
|
namespace Volo.Abp.Logging |
||||
|
{ |
||||
|
public class DefaultInitLogger<T> : IInitLogger<T> |
||||
|
{ |
||||
|
public List<AbpInitLogEntry> Entries { get; } |
||||
|
|
||||
|
public DefaultInitLogger() |
||||
|
{ |
||||
|
Entries = new List<AbpInitLogEntry>(); |
||||
|
} |
||||
|
|
||||
|
public virtual void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) |
||||
|
{ |
||||
|
Entries.Add(new AbpInitLogEntry |
||||
|
{ |
||||
|
LogLevel = logLevel, |
||||
|
EventId = eventId, |
||||
|
State = state, |
||||
|
Exception = exception, |
||||
|
Formatter = (s, e) => formatter((TState)s, e), |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public virtual bool IsEnabled(LogLevel logLevel) |
||||
|
{ |
||||
|
return logLevel != LogLevel.None; |
||||
|
} |
||||
|
|
||||
|
public virtual IDisposable BeginScope<TState>(TState state) |
||||
|
{ |
||||
|
return NullDisposable.Instance; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Volo.Abp.Logging |
||||
|
{ |
||||
|
public class DefaultInitLoggerFactory : IInitLoggerFactory |
||||
|
{ |
||||
|
private readonly Dictionary<Type, object> _cache = new Dictionary<Type, object>(); |
||||
|
|
||||
|
public virtual IInitLogger<T> Create<T>() |
||||
|
{ |
||||
|
return (IInitLogger<T>)_cache.GetOrAdd(typeof(T), () => new DefaultInitLogger<T>());; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
|
||||
|
namespace Volo.Abp.Logging |
||||
|
{ |
||||
|
public interface IInitLogger<out T> : ILogger<T> |
||||
|
{ |
||||
|
public List<AbpInitLogEntry> Entries { get; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
namespace Volo.Abp.Logging |
||||
|
{ |
||||
|
public interface IInitLoggerFactory |
||||
|
{ |
||||
|
IInitLogger<T> Create<T>(); |
||||
|
} |
||||
|
} |
||||
@ -1,21 +1,23 @@ |
|||||
using System; |
using System; |
||||
using System.Linq; |
using System.Linq; |
||||
using JetBrains.Annotations; |
using JetBrains.Annotations; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using Volo.Abp.Logging; |
||||
|
|
||||
namespace Volo.Abp.Modularity.PlugIns |
namespace Volo.Abp.Modularity.PlugIns |
||||
{ |
{ |
||||
public static class PlugInSourceExtensions |
public static class PlugInSourceExtensions |
||||
{ |
{ |
||||
[NotNull] |
[NotNull] |
||||
public static Type[] GetModulesWithAllDependencies([NotNull] this IPlugInSource plugInSource) |
public static Type[] GetModulesWithAllDependencies([NotNull] this IPlugInSource plugInSource, ILogger logger) |
||||
{ |
{ |
||||
Check.NotNull(plugInSource, nameof(plugInSource)); |
Check.NotNull(plugInSource, nameof(plugInSource)); |
||||
|
|
||||
return plugInSource |
return plugInSource |
||||
.GetModules() |
.GetModules() |
||||
.SelectMany(AbpModuleHelper.FindAllModuleTypes) |
.SelectMany(type => AbpModuleHelper.FindAllModuleTypes(type, logger)) |
||||
.Distinct() |
.Distinct() |
||||
.ToArray(); |
.ToArray(); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -1,22 +1,124 @@ |
|||||
{ |
{ |
||||
"culture": "zh-Hans", |
"culture": "zh-Hans", |
||||
"texts": { |
"texts": { |
||||
"PickYourReaction": "选择你的回应", |
"BlogDeletionConfirmationMessage": "博客 '{0}' 将被删除. 你确定吗?", |
||||
"YourComment": "你的评论", |
"BlogFeatureNotAvailable": "这个功能目前不可用. 使用 `GlobalFeatureManager` 来启用它.", |
||||
"YourReply": "你的回复", |
"BlogId": "博客", |
||||
|
"BlogPostDeletionConfirmationMessage": "博客帖子 '{0}' 将被删除. 你确定吗?", |
||||
|
"BlogPosts": "博客帖子", |
||||
|
"Blogs": "博客", |
||||
|
"ChoosePreference": "选择首选项...", |
||||
|
"Cms": "Cms", |
||||
|
"CmsKit.Comments": "评论", |
||||
|
"CmsKit.Ratings": "评分", |
||||
|
"CmsKit.Reactions": "反应", |
||||
|
"CmsKit.Tags": "标签", |
||||
|
"CmsKit:0002": "内容已经存在!", |
||||
|
"CmsKit:0003": "实体 {0} 不可标记.", |
||||
|
"CmsKit:Blog:0001": "给定的slug ({Slug}) 已经存在!", |
||||
|
"CmsKit:BlogPost:0001": "给定的slug已经存在!", |
||||
|
"CmsKit:Comments:0001": "实体不可 {0} 不可评论.", |
||||
|
"CmsKit:Media:0001": "'{Name}' 不是有效的媒体名称.", |
||||
|
"CmsKit:Media:0002": "实体不可以含有媒体", |
||||
|
"CmsKit:Page:0001": "给定的url ({0}) 已经存在.", |
||||
|
"CmsKit:Tag:0002": "实体不可标记!", |
||||
|
"CommentAuthorizationExceptionMessage": "这些评论不允许公开显示", |
||||
|
"CommentDeletionConfirmationMessage": "此评论和所有回复将被删除!", |
||||
"Comments": "评论", |
"Comments": "评论", |
||||
"Send": "发送", |
"ContentDeletionConfirmationMessage": "你确定要删除这个内容吗?", |
||||
|
"Contents": "内容", |
||||
|
"CoverImage": "封面图片", |
||||
|
"CreateBlogPostPage": "新博客帖子", |
||||
|
"CreationTime": "创建时间", |
||||
"Delete": "删除", |
"Delete": "删除", |
||||
"Reply": "回复", |
"Detail": "详情", |
||||
"Update": "更新", |
"Details": "详情", |
||||
|
"DoYouPreferAdditionalEmails": "你是否更喜欢额外的邮件?", |
||||
"Edit": "修改", |
"Edit": "修改", |
||||
|
"EndDate": "结束时间", |
||||
|
"EntityId": "实体Id", |
||||
|
"EntityType": "实体类型", |
||||
|
"ExportCSV": "导出CSV", |
||||
|
"Features": "功能", |
||||
|
"GenericDeletionConfirmationMessage": "你确定删除 '{0}' 吗?", |
||||
|
"LastModification": "最后一次修改", |
||||
"LoginToAddComment": "登录添加评论", |
"LoginToAddComment": "登录添加评论", |
||||
|
"LoginToRate": "登录进行评分", |
||||
"LoginToReply": "登录进行回复", |
"LoginToReply": "登录进行回复", |
||||
|
"Menu:CMS": "CMS", |
||||
|
"Message": "消息", |
||||
"MessageDeletionConfirmationMessage": "这条评论将被完全删除", |
"MessageDeletionConfirmationMessage": "这条评论将被完全删除", |
||||
"CommentAuthorizationExceptionMessage": "这些评论不允许公开显示", |
"Name": "名称", |
||||
"Undo": "撤消", |
"New": "新", |
||||
|
"OK": "OK", |
||||
|
"PageDeletionConfirmationMessage": "你确定删除这个页面吗?", |
||||
|
"PageSlugInformation": "Slug用于url. 你的url将是 '/pages/{{slug}}'.", |
||||
|
"Permission:BlogManagement": "博客管理", |
||||
|
"Permission:BlogManagement.Create": "创建", |
||||
|
"Permission:BlogManagement.Delete": "删除", |
||||
|
"Permission:BlogManagement.Features": "删除", |
||||
|
"Permission:BlogManagement.Update": "更新", |
||||
|
"Permission:BlogPostManagement": "博客帖子管理", |
||||
|
"Permission:BlogPostManagement.Create": "创建", |
||||
|
"Permission:BlogPostManagement.Delete": "删除", |
||||
|
"Permission:BlogPostManagement.Update": "更新", |
||||
|
"Permission:CmsKit": "Cms工具包", |
||||
|
"Permission:Comments": "评论管理", |
||||
|
"Permission:Comments.Delete": "删除", |
||||
|
"Permission:Contents": "内容管理", |
||||
|
"Permission:Contents.Create": "创建内容", |
||||
|
"Permission:Contents.Delete": "删除内容", |
||||
|
"Permission:Contents.Update": "更新内容", |
||||
|
"Permission:MediaDescriptorManagement": "媒体管理", |
||||
|
"Permission:MediaDescriptorManagement:Create": "创建", |
||||
|
"Permission:MediaDescriptorManagement:Delete": "删除", |
||||
|
"Permission:PageManagement": "页面管理", |
||||
|
"Permission:PageManagement:Create": "创建", |
||||
|
"Permission:PageManagement:Delete": "删除", |
||||
|
"Permission:PageManagement:Update": "更新", |
||||
|
"Permission:TagManagement": "标签管理", |
||||
|
"Permission:TagManagement.Create": "创建", |
||||
|
"Permission:TagManagement.Delete": "删除", |
||||
|
"Permission:TagManagement.Update": "更新", |
||||
|
"PickYourReaction": "选择你的回应", |
||||
"RatingUndoMessage": "您的评分将被撤消", |
"RatingUndoMessage": "您的评分将被撤消", |
||||
"LoginToRate": "登录进行评分", |
"Read": "阅读", |
||||
"Star": "星" |
"RepliesToThisComment": "回复此评论", |
||||
|
"Reply": "回复", |
||||
|
"ReplyTo": "回复", |
||||
|
"SamplePageMessage": "Pro模块的示例页面", |
||||
|
"SaveChanges": "保存更改", |
||||
|
"SelectAll": "选择所有", |
||||
|
"Send": "发送", |
||||
|
"SendMessage": "发送消息", |
||||
|
"ShortDescription": "简介", |
||||
|
"Slug": "Slug", |
||||
|
"Source": "源", |
||||
|
"SourceUrl": "源URL", |
||||
|
"Star": "星", |
||||
|
"StartDate": "开始时间", |
||||
|
"Subject": "主题", |
||||
|
"SubjectPlaceholder": "请输入主题", |
||||
|
"Submit": "提交", |
||||
|
"Subscribe": "订阅", |
||||
|
"SuccessfullyDeleted": "删除成功!", |
||||
|
"SuccessfullySaved": "保存成功!", |
||||
|
"TagDeletionConfirmationMessage": "你确定删除 '{0}' 标签吗?", |
||||
|
"Tags": "标签", |
||||
|
"Text": "文本", |
||||
|
"ThankYou": "谢谢你", |
||||
|
"Title": "标题", |
||||
|
"Undo": "撤消", |
||||
|
"Update": "更新", |
||||
|
"UpdatePreferenceSuccessMessage": "您的首选项已经保存", |
||||
|
"UpdateYourEmailPreferences": "更新你的邮件首选项", |
||||
|
"UploadFailedMessage": "上传失败", |
||||
|
"UserId": "用户Id", |
||||
|
"Username": "用户名称", |
||||
|
"YourComment": "你的评论", |
||||
|
"YourEmailAddress": "你的邮件地址", |
||||
|
"YourFullName": "你的全称", |
||||
|
"YourMessage": "你的消息", |
||||
|
"YourReply": "你的回复" |
||||
} |
} |
||||
} |
} |
||||
@ -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>(); |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
|
||||
|
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)); |
||||
|
Check.NotNullOrWhiteSpace(entityType, nameof(entityType), CommentConsts.MaxEntityTypeLength); |
||||
|
Check.NotNullOrWhiteSpace(entityId, nameof(entityId), CommentConsts.MaxEntityIdLength); |
||||
|
Check.NotNullOrWhiteSpace(text, nameof(text), CommentConsts.MaxTextLength); |
||||
|
|
||||
|
if (!await DefinitionStore.IsDefinedAsync(entityType)) |
||||
|
{ |
||||
|
throw new EntityNotCommentableException(entityType); |
||||
|
} |
||||
|
|
||||
|
return new Comment( |
||||
|
GuidGenerator.Create(), |
||||
|
entityType, |
||||
|
entityId, |
||||
|
text, |
||||
|
repliedCommentId, |
||||
|
creator.Id, |
||||
|
CurrentTenant.Id); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
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 |
||||
|
{ |
||||
|
[Serializable] |
||||
|
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; } |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace Volo.Abp.Identity |
||||
|
{ |
||||
|
[Serializable] |
||||
|
public class IdentityRoleNameChangedEto |
||||
|
{ |
||||
|
public Guid Id { get; set; } |
||||
|
|
||||
|
public Guid? TenantId { get; set; } |
||||
|
|
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
public string OldName { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -1,26 +1,27 @@ |
|||||
using System.Threading.Tasks; |
using System.Threading.Tasks; |
||||
using Volo.Abp.Authorization.Permissions; |
using Volo.Abp.Authorization.Permissions; |
||||
using Volo.Abp.DependencyInjection; |
using Volo.Abp.DependencyInjection; |
||||
using Volo.Abp.Domain.Entities.Events; |
using Volo.Abp.Domain.Entities.Events.Distributed; |
||||
using Volo.Abp.EventBus; |
using Volo.Abp.EventBus; |
||||
|
using Volo.Abp.EventBus.Distributed; |
||||
using Volo.Abp.Identity; |
using Volo.Abp.Identity; |
||||
|
|
||||
namespace Volo.Abp.PermissionManagement.Identity |
namespace Volo.Abp.PermissionManagement.Identity |
||||
{ |
{ |
||||
// public class RoleDeletedEventHandler :
|
public class RoleDeletedEventHandler : |
||||
// ILocalEventHandler<EntityDeletedEventData<IdentityRole>>,
|
IDistributedEventHandler<EntityDeletedEto<IdentityRoleEto>>, |
||||
// ITransientDependency
|
ITransientDependency |
||||
// {
|
{ |
||||
// protected IPermissionManager PermissionManager { get; }
|
protected IPermissionManager PermissionManager { get; } |
||||
//
|
|
||||
// public RoleDeletedEventHandler(IPermissionManager permissionManager)
|
public RoleDeletedEventHandler(IPermissionManager permissionManager) |
||||
// {
|
{ |
||||
// PermissionManager = permissionManager;
|
PermissionManager = permissionManager; |
||||
// }
|
} |
||||
//
|
|
||||
// public virtual async Task HandleEventAsync(EntityDeletedEventData<IdentityRole> eventData)
|
public async Task HandleEventAsync(EntityDeletedEto<IdentityRoleEto> eventData) |
||||
// {
|
{ |
||||
// await PermissionManager.DeleteAsync(RolePermissionValueProvider.ProviderName, eventData.Entity.Name);
|
await PermissionManager.DeleteAsync(RolePermissionValueProvider.ProviderName, eventData.Entity.Name); |
||||
// }
|
} |
||||
// }
|
} |
||||
} |
} |
||||
|
|||||
@ -1,45 +1,33 @@ |
|||||
using System.Threading.Tasks; |
using System.Threading.Tasks; |
||||
using Volo.Abp.Authorization.Permissions; |
using Volo.Abp.Authorization.Permissions; |
||||
using Volo.Abp.DependencyInjection; |
using Volo.Abp.DependencyInjection; |
||||
using Volo.Abp.Domain.Entities.Events; |
using Volo.Abp.EventBus.Distributed; |
||||
using Volo.Abp.EventBus; |
|
||||
using Volo.Abp.Identity; |
using Volo.Abp.Identity; |
||||
|
|
||||
namespace Volo.Abp.PermissionManagement.Identity |
namespace Volo.Abp.PermissionManagement.Identity |
||||
{ |
{ |
||||
//TODO: This code can not be here!
|
public class RoleUpdateEventHandler : |
||||
|
IDistributedEventHandler<IdentityRoleNameChangedEto>, |
||||
|
ITransientDependency |
||||
|
{ |
||||
|
protected IPermissionManager PermissionManager { get; } |
||||
|
protected IPermissionGrantRepository PermissionGrantRepository { get; } |
||||
|
|
||||
|
public RoleUpdateEventHandler( |
||||
|
IPermissionManager permissionManager, |
||||
|
IPermissionGrantRepository permissionGrantRepository) |
||||
|
{ |
||||
|
PermissionManager = permissionManager; |
||||
|
PermissionGrantRepository = permissionGrantRepository; |
||||
|
} |
||||
|
|
||||
// public class RoleUpdateEventHandler :
|
public async Task HandleEventAsync(IdentityRoleNameChangedEto eventData) |
||||
// ILocalEventHandler<IdentityRoleNameChangedEvent>,
|
{ |
||||
// ITransientDependency
|
var permissionGrantsInRole = await PermissionGrantRepository.GetListAsync(RolePermissionValueProvider.ProviderName, eventData.OldName); |
||||
// {
|
foreach (var permissionGrant in permissionGrantsInRole) |
||||
// protected IIdentityRoleRepository RoleRepository { get; }
|
{ |
||||
// protected IPermissionManager PermissionManager { get; }
|
await PermissionManager.UpdateProviderKeyAsync(permissionGrant, eventData.Name); |
||||
// protected IPermissionGrantRepository PermissionGrantRepository { get; }
|
} |
||||
//
|
} |
||||
// public RoleUpdateEventHandler(
|
} |
||||
// IIdentityRoleRepository roleRepository,
|
|
||||
// IPermissionManager permissionManager,
|
|
||||
// IPermissionGrantRepository permissionGrantRepository)
|
|
||||
// {
|
|
||||
// RoleRepository = roleRepository;
|
|
||||
// PermissionManager = permissionManager;
|
|
||||
// PermissionGrantRepository = permissionGrantRepository;
|
|
||||
// }
|
|
||||
//
|
|
||||
// public virtual async Task HandleEventAsync(IdentityRoleNameChangedEvent eventData)
|
|
||||
// {
|
|
||||
// var role = await RoleRepository.FindAsync(eventData.IdentityRole.Id, false);
|
|
||||
// if (role == null)
|
|
||||
// {
|
|
||||
// return;
|
|
||||
// }
|
|
||||
//
|
|
||||
// var permissionGrantsInRole = await PermissionGrantRepository.GetListAsync(RolePermissionValueProvider.ProviderName, eventData.OldName);
|
|
||||
// foreach (var permissionGrant in permissionGrantsInRole)
|
|
||||
// {
|
|
||||
// await PermissionManager.UpdateProviderKeyAsync(permissionGrant, eventData.IdentityRole.Name);
|
|
||||
// }
|
|
||||
// }
|
|
||||
// }
|
|
||||
} |
} |
||||
|
|||||
@ -0,0 +1,105 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using Microsoft.AspNetCore.Identity; |
||||
|
using Shouldly; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Volo.Abp.Caching; |
||||
|
using Volo.Abp.Domain.Entities.Events.Distributed; |
||||
|
using Volo.Abp.EventBus.Distributed; |
||||
|
using Volo.Abp.PermissionManagement; |
||||
|
using Volo.Abp.PermissionManagement.Identity; |
||||
|
using Volo.Abp.Uow; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Volo.Abp.Identity |
||||
|
{ |
||||
|
public class Distributed_Role_Change_Events_Test : AbpIdentityDomainTestBase |
||||
|
{ |
||||
|
protected readonly IIdentityRoleRepository RoleRepository; |
||||
|
protected readonly IPermissionGrantRepository PermissionGrantRepository; |
||||
|
protected readonly IdentityRoleManager RoleManager; |
||||
|
protected readonly ILookupNormalizer LookupNormalizer; |
||||
|
protected readonly IUnitOfWorkManager UowManager; |
||||
|
protected readonly IDistributedCache<PermissionGrantCacheItem> Cache; |
||||
|
|
||||
|
public Distributed_Role_Change_Events_Test() |
||||
|
{ |
||||
|
RoleRepository = GetRequiredService<IIdentityRoleRepository>(); |
||||
|
; |
||||
|
PermissionGrantRepository = GetRequiredService<IPermissionGrantRepository>(); |
||||
|
; |
||||
|
RoleManager = GetRequiredService<IdentityRoleManager>(); |
||||
|
; |
||||
|
LookupNormalizer = GetRequiredService<ILookupNormalizer>(); |
||||
|
; |
||||
|
UowManager = GetRequiredService<IUnitOfWorkManager>(); |
||||
|
Cache = GetRequiredService<IDistributedCache<PermissionGrantCacheItem>>(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_Register_Handler() |
||||
|
{ |
||||
|
var x = GetRequiredService<IOptions<AbpDistributedEntityEventOptions>>(); |
||||
|
GetRequiredService<IOptions<AbpDistributedEntityEventOptions>>() |
||||
|
.Value |
||||
|
.AutoEventSelectors |
||||
|
.ShouldContain(m => m.Name == "Entity:" + typeof(IdentityRole).FullName); |
||||
|
|
||||
|
GetRequiredService<IOptions<AbpDistributedEventBusOptions>>() |
||||
|
.Value |
||||
|
.Handlers |
||||
|
.ShouldContain(h => h == typeof(RoleUpdateEventHandler) || h == typeof(RoleDeletedEventHandler)); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Role_Updated_Distributed_Event_Test() |
||||
|
{ |
||||
|
var role = await RoleRepository.FindByNormalizedNameAsync(LookupNormalizer.NormalizeName("moderator")); |
||||
|
|
||||
|
var permissionGrantsInRole = await PermissionGrantRepository.GetListAsync("R", role.Name); |
||||
|
permissionGrantsInRole.ShouldNotBeNull(); |
||||
|
permissionGrantsInRole.Count.ShouldBeGreaterThan(0); |
||||
|
var count = permissionGrantsInRole.Count; |
||||
|
|
||||
|
using (var uow = UowManager.Begin()) |
||||
|
{ |
||||
|
var identityResult = await RoleManager.SetRoleNameAsync(role, "TestModerator"); |
||||
|
identityResult.Succeeded.ShouldBeTrue(); |
||||
|
await RoleRepository.UpdateAsync(role); |
||||
|
await uow.CompleteAsync(); |
||||
|
} |
||||
|
|
||||
|
role = await RoleRepository.GetAsync(role.Id); |
||||
|
role.Name.ShouldBe("TestModerator"); |
||||
|
|
||||
|
permissionGrantsInRole = await PermissionGrantRepository.GetListAsync("R", role.Name); |
||||
|
permissionGrantsInRole.Count.ShouldBe(count); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Role_Deleted_Distributed_Event_Test() |
||||
|
{ |
||||
|
var role = await RoleRepository.FindByNormalizedNameAsync(LookupNormalizer.NormalizeName("moderator")); |
||||
|
var permissionGrantsInRole = await PermissionGrantRepository.GetListAsync("R", role.Name); |
||||
|
|
||||
|
var caches = permissionGrantsInRole.Select(x => new KeyValuePair<string, PermissionGrantCacheItem>( |
||||
|
PermissionGrantCacheItem.CalculateCacheKey(x.Name, x.ProviderName, x.ProviderKey), |
||||
|
new PermissionGrantCacheItem(true))).ToList(); |
||||
|
await Cache.SetManyAsync(caches); |
||||
|
|
||||
|
|
||||
|
using (var uow = UowManager.Begin()) |
||||
|
{ |
||||
|
await RoleRepository.DeleteAsync(role); |
||||
|
await uow.CompleteAsync(); |
||||
|
} |
||||
|
|
||||
|
var permissionGrantCaches = await Cache.GetManyAsync(caches.Select(x=>x.Key)); |
||||
|
foreach (var cache in permissionGrantCaches) |
||||
|
{ |
||||
|
cache.Value.ShouldBeNull(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
{ |
||||
|
"culture": "zh-Hans", |
||||
|
"texts": { |
||||
|
"Volo.Abp.Identity:PasswordTooShort": "密码长度必须大于{0}字符. ", |
||||
|
"Volo.Abp.Identity:PasswordRequiresNonAlphanumeric": "密码必须至少包含一个非字母数字字符." |
||||
|
} |
||||
|
} |
||||
@ -1,60 +0,0 @@ |
|||||
using Microsoft.AspNetCore.Identity; |
|
||||
using Shouldly; |
|
||||
using System.Threading.Tasks; |
|
||||
using Volo.Abp.EventBus.Distributed; |
|
||||
using Volo.Abp.Guids; |
|
||||
using Volo.Abp.PermissionManagement; |
|
||||
using Volo.Abp.Uow; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace Volo.Abp.Identity |
|
||||
{ |
|
||||
//TODO: This code can not be here!
|
|
||||
//https://github.com/abpframework/abp/commit/847f526041145b62376b760776829d5ce257da1c
|
|
||||
// public class RoleChangingEvents_Test : AbpIdentityDomainTestBase
|
|
||||
// {
|
|
||||
// protected readonly IIdentityRoleRepository RoleRepository;
|
|
||||
// protected readonly IPermissionGrantRepository PermissionGrantRepository;
|
|
||||
// protected readonly IdentityRoleManager RoleManager;
|
|
||||
// protected readonly ILookupNormalizer LookupNormalizer;
|
|
||||
// protected readonly IGuidGenerator GuidGenerator;
|
|
||||
// protected readonly IUnitOfWorkManager UowManager;
|
|
||||
//
|
|
||||
// public RoleChangingEvents_Test()
|
|
||||
// {
|
|
||||
// RoleRepository = GetRequiredService<IIdentityRoleRepository>(); ;
|
|
||||
// PermissionGrantRepository = GetRequiredService<IPermissionGrantRepository>(); ;
|
|
||||
// RoleManager = GetRequiredService<IdentityRoleManager>(); ;
|
|
||||
// LookupNormalizer = GetRequiredService<ILookupNormalizer>(); ;
|
|
||||
// GuidGenerator = GetRequiredService<IGuidGenerator>();
|
|
||||
// UowManager = GetRequiredService<IUnitOfWorkManager>();
|
|
||||
// }
|
|
||||
//
|
|
||||
// [Fact(Skip = "https://github.com/abpframework/abp/actions/runs/454248191")]
|
|
||||
// public async Task Role_Update_Event_Test()
|
|
||||
// {
|
|
||||
// var role = await RoleRepository
|
|
||||
// .FindByNormalizedNameAsync(LookupNormalizer.NormalizeName("moderator"))
|
|
||||
// ;
|
|
||||
//
|
|
||||
// var permissionGrantsInRole = await PermissionGrantRepository.GetListAsync("R", role.Name);
|
|
||||
// permissionGrantsInRole.ShouldNotBeNull();
|
|
||||
// permissionGrantsInRole.Count.ShouldBeGreaterThan(0);
|
|
||||
// var count = permissionGrantsInRole.Count;
|
|
||||
//
|
|
||||
// using (var uow = UowManager.Begin())
|
|
||||
// {
|
|
||||
// var identityResult = await RoleManager.SetRoleNameAsync(role, "TestModerator");
|
|
||||
// identityResult.Succeeded.ShouldBeTrue();
|
|
||||
// var xx = await RoleRepository.UpdateAsync(role);
|
|
||||
// await uow.CompleteAsync();
|
|
||||
// }
|
|
||||
//
|
|
||||
// role = await RoleRepository.GetAsync(role.Id);
|
|
||||
// role.Name.ShouldBe("TestModerator");
|
|
||||
//
|
|
||||
// permissionGrantsInRole = await PermissionGrantRepository.GetListAsync("R", role.Name);
|
|
||||
// permissionGrantsInRole.Count.ShouldBe(count);
|
|
||||
// }
|
|
||||
// }
|
|
||||
} |
|
||||
@ -0,0 +1,7 @@ |
|||||
|
/* |
||||
|
https://jquery.com/upgrade-guide/3.5/#jquery-htmlprefilter-changes
|
||||
|
*/ |
||||
|
var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi; |
||||
|
jQuery.htmlPrefilter = function( html ) { |
||||
|
return html.replace( rxhtmlTag, "<$1></$2>" ); |
||||
|
}; |
||||
Loading…
Reference in new issue