Merge pull request #16445 from abpframework/auto-merge/rel-7-2/1915

Merge branch dev with rel-7.2
pull/16446/head
Engincan VESKE 2 years ago committed by GitHub
commit 3f5d63e25a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -25,7 +25,8 @@ namespace Volo.CmsKit.Public.Comments;
[RequiresGlobalFeature(typeof(CommentsFeature))]
public class CommentPublicAppService : CmsKitPublicAppServiceBase, ICommentPublicAppService
{
protected string RegexMarkdownUrlPattern = @"\[[^\]]*\]\((?<url>.*?)\)(?![^\x60]*\x60)";
protected string RegexUrlPattern =
@"https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()!@:%_\+.~#?&\/\/=]*)";
protected ICommentRepository CommentRepository { get; }
protected ICmsUserLookupService CmsUserLookupService { get; }
@ -124,7 +125,41 @@ public class CommentPublicAppService : CmsKitPublicAppServiceBase, ICommentPubli
throw new AbpAuthorizationException();
}
}
protected virtual void CheckExternalUrls(string entityType, string text)
{
if (!CmsCommentOptions.AllowedExternalUrls.TryGetValue(entityType, out var allowedExternalUrls))
{
return;
}
text = text.Replace("www.", "https://www.").Replace("://https", "");
var matches = Regex.Matches(text, RegexUrlPattern,
RegexOptions.Compiled | RegexOptions.IgnoreCase);
foreach (Match match in matches)
{
if (!match.Success || match.Groups.Count <= 0)
{
continue;
}
var normalizedFullUrl = NormalizeUrl(match.Groups[0].Value);
if (!allowedExternalUrls.Any(allowedExternalUrl =>
normalizedFullUrl.Contains(NormalizeUrl(allowedExternalUrl), StringComparison.OrdinalIgnoreCase)))
{
throw new UserFriendlyException(L["UnAllowedExternalUrlMessage"]);
}
}
}
private static string NormalizeUrl(string url)
{
return url.Replace("www.", "").RemovePostFix("/");
}
private List<CommentWithDetailsDto> ConvertCommentsToNestedStructure(List<CommentWithAuthorQueryResultItem> comments)
{
//TODO: I think this method can be optimized if you use dictionaries instead of straight search
@ -156,46 +191,4 @@ public class CommentPublicAppService : CmsKitPublicAppServiceBase, ICommentPubli
{
return ObjectMapper.Map<CmsUser, CmsUserDto>(comments.Single(c => c.Comment.Id == commentId).Author);
}
private void CheckExternalUrls(string entityType, string text)
{
if (!CmsCommentOptions.AllowedExternalUrls.TryGetValue(entityType, out var allowedExternalUrls))
{
return;
}
var matches = Regex.Matches(text, RegexMarkdownUrlPattern,
RegexOptions.Compiled | RegexOptions.IgnoreCase);
foreach (Match match in matches)
{
if (!match.Success || match.Groups.Count < 2)
{
continue;
}
var url = NormalizeUrl(match.Groups[1].Value);
if (!IsExternalUrl(url))
{
continue;
}
if (!allowedExternalUrls.Any(allowedExternalUrl =>
url.Contains(NormalizeUrl(allowedExternalUrl), StringComparison.OrdinalIgnoreCase)))
{
throw new UserFriendlyException(L["UnAllowedExternalUrlMessage"]);
}
}
}
private static bool IsExternalUrl(string url)
{
return url.StartsWith("https", StringComparison.InvariantCultureIgnoreCase) ||
url.StartsWith("http", StringComparison.InvariantCultureIgnoreCase);
}
private static string NormalizeUrl(string url)
{
return url.Replace("www.", "").RemovePostFix("/");
}
}

@ -62,9 +62,28 @@ public class CommentPublicAppService_Tests : CmsKitApplicationTestBase
.ShouldBeTrue();
});
}
[Theory]
[InlineData("https://abp.io/features")]
public async Task CreateAsync_ShouldCreateComment_If_Url_Allowed(string text)
{
_currentUser.Id.Returns(_cmsKitTestData.User2Id);
[Fact]
public async Task CreateAsync_ShouldThrowUserFriendlyException_If_Url_UnAllowed()
await _commentAppService.CreateAsync(
_cmsKitTestData.EntityType1,
_cmsKitTestData.EntityId1,
new CreateCommentInput
{
RepliedCommentId = null,
Text = text
}
);
}
[Theory]
[InlineData("[ABP Community](https://community.abp.io/)")]
[InlineData("<a href='https://docs.abp.io/en/abp/latest'>docs.abp.io</a>")]
public async Task CreateAsync_ShouldThrowUserFriendlyException_If_Url_UnAllowed(string text)
{
_currentUser.Id.Returns(_cmsKitTestData.User2Id);
@ -75,7 +94,7 @@ public class CommentPublicAppService_Tests : CmsKitApplicationTestBase
new CreateCommentInput
{
RepliedCommentId = null,
Text = "[ABP Community](https://community.abp.io/)", //not allowed URL
Text = text, //not allowed URL
}
));
}

Loading…
Cancel
Save