From 636935ce5b163ab233b0ae5aa2a8f553ea3ed693 Mon Sep 17 00:00:00 2001 From: malik masis Date: Tue, 6 Dec 2022 15:51:14 +0300 Subject: [PATCH 01/22] Added Delete for the public side --- .../Public/Blogs/IBlogPostPublicAppService.cs | 1 + .../Public/Blogs/BlogPostPublicAppService.cs | 17 ++++++++++++++++- .../Public/Blogs/BlogPostPublicController.cs | 11 +++++++++-- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Blogs/IBlogPostPublicAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Blogs/IBlogPostPublicAppService.cs index a6462d937c..dd21e2c903 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Blogs/IBlogPostPublicAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Blogs/IBlogPostPublicAppService.cs @@ -17,4 +17,5 @@ public interface IBlogPostPublicAppService : IApplicationService Task> GetAuthorsHasBlogPostsAsync(BlogPostFilteredPagedAndSortedResultRequestDto input); Task GetAuthorHasBlogPostAsync(Guid id); + Task DeleteAsync(Guid id); } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Blogs/BlogPostPublicAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Blogs/BlogPostPublicAppService.cs index 5041406bd0..91b7936251 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Blogs/BlogPostPublicAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Blogs/BlogPostPublicAppService.cs @@ -2,11 +2,13 @@ using System.Collections.Generic; using System.Threading.Tasks; using JetBrains.Annotations; +using Microsoft.AspNetCore.Authorization; using Volo.Abp.Application.Dtos; +using Volo.Abp.Authorization; using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; +using Volo.Abp.Users; using Volo.CmsKit.Blogs; - using Volo.CmsKit.Contents; using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; @@ -70,4 +72,17 @@ public class BlogPostPublicAppService : CmsKitPublicAppServiceBase, IBlogPostPub return ObjectMapper.Map(author); } + + [Authorize] + public async Task DeleteAsync(Guid id) + { + var rating = await BlogPostRepository.GetAsync(id); + + if (rating.CreatorId != CurrentUser.GetId()) + { + throw new AbpAuthorizationException(); + } + + await BlogPostRepository.DeleteAsync(id); + } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Blogs/BlogPostPublicController.cs b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Blogs/BlogPostPublicController.cs index e5d2570e21..4d2a336fca 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Blogs/BlogPostPublicController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Blogs/BlogPostPublicController.cs @@ -42,15 +42,22 @@ public class BlogPostPublicController : CmsKitPublicControllerBase, IBlogPostPub [HttpGet] [Route("authors")] - public Task> GetAuthorsHasBlogPostsAsync(BlogPostFilteredPagedAndSortedResultRequestDto input) + public virtual Task> GetAuthorsHasBlogPostsAsync(BlogPostFilteredPagedAndSortedResultRequestDto input) { return BlogPostPublicAppService.GetAuthorsHasBlogPostsAsync(input); } [HttpGet] [Route("authors/{id}")] - public Task GetAuthorHasBlogPostAsync(Guid id) + public virtual Task GetAuthorHasBlogPostAsync(Guid id) { return BlogPostPublicAppService.GetAuthorHasBlogPostAsync(id); } + + [HttpDelete] + [Route("{id}")] + public virtual Task DeleteAsync(Guid id) + { + return BlogPostPublicAppService.DeleteAsync(id); + } } \ No newline at end of file From 9027efbb020984c016e1238ea294034fdc34d7e2 Mon Sep 17 00:00:00 2001 From: malik masis Date: Tue, 6 Dec 2022 15:51:23 +0300 Subject: [PATCH 02/22] Update cms-kit-proxy.js --- .../wwwroot/client-proxies/cms-kit-proxy.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/wwwroot/client-proxies/cms-kit-proxy.js b/modules/cms-kit/src/Volo.CmsKit.Public.Web/wwwroot/client-proxies/cms-kit-proxy.js index ec98417af5..2d2be254a6 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/wwwroot/client-proxies/cms-kit-proxy.js +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/wwwroot/client-proxies/cms-kit-proxy.js @@ -214,6 +214,14 @@ }, ajaxParams)); }; + volo.cmsKit.public.blogs.blogPostPublic['delete'] = function(id, ajaxParams) { + return abp.ajax($.extend(true, { + url: abp.appPath + 'api/cms-kit-public/blog-posts/' + id + '', + type: 'DELETE', + dataType: null + }, ajaxParams)); + }; + })(); })(); From b7b8bd1ea07643a369909864a0eb18bdbe0bb9df Mon Sep 17 00:00:00 2001 From: malik masis Date: Tue, 6 Dec 2022 15:51:46 +0300 Subject: [PATCH 03/22] Completed the ui side --- .../Pages/Public/CmsKit/Blogs/BlogPost.cshtml | 58 +++++++++++-------- .../Pages/Public/CmsKit/Blogs/blogPost.js | 16 +++++ .../Pages/Public/CmsKit/Blogs/index.js | 8 +-- .../Volo.CmsKit.Public.Web.csproj | 4 ++ 4 files changed, 57 insertions(+), 29 deletions(-) create mode 100644 modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/blogPost.js diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml index d5dc5a0be8..789890704d 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml @@ -50,14 +50,15 @@ + } -
+
@@ -109,10 +110,10 @@ if (Model.ReactionsFeature?.IsEnabled == true) { @await Component.InvokeAsync(typeof(ReactionSelectionViewComponent), new - { - entityType = Volo.CmsKit.Blogs.BlogPostConsts.EntityType, - entityId = Model.ViewModel.Id.ToString() - }) + { + entityType = Volo.CmsKit.Blogs.BlogPostConsts.EntityType, + entityId = Model.ViewModel.Id.ToString() + }) } } @@ -122,10 +123,10 @@ if (Model.RatingsFeature?.IsEnabled == true) { @await Component.InvokeAsync(typeof(RatingViewComponent), new - { - entityType = Volo.CmsKit.Blogs.BlogPostConsts.EntityType, - entityId = Model.ViewModel.Id.ToString() - }) + { + entityType = Volo.CmsKit.Blogs.BlogPostConsts.EntityType, + entityId = Model.ViewModel.Id.ToString() + }) } } @@ -133,24 +134,31 @@
- @if (isScrollIndexEnabled) - { -
-
-
@L["InThisDocument"]
- - -
-
- - @L["GoToTop"] - + +
+ + + @if (isScrollIndexEnabled) + { +
+
@L["InThisDocument"]
+ + +
-
-
- } + } +
diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/blogPost.js b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/blogPost.js new file mode 100644 index 0000000000..160cfd3b65 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/blogPost.js @@ -0,0 +1,16 @@ +$(function () { + + let l = abp.localization.getResource("CmsKit"); + + $('#deleteBlogPost').on('click', '', function (e) { + abp.message.confirm(l("DeleteBlogPostMessage"), function (ok) { + if (ok) { + volo.cmsKit.public.blogs.blogPostPublic.delete( + $('#BlogId').val() + ).then(function () { + document.location.href = "/"; + }); + } + }) + }); +}); diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/index.js b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/index.js index 0d567d1650..dde3ed4e89 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/index.js +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/index.js @@ -1,14 +1,14 @@ $(function () { - var $selectAuthor = $('#AuthorSelect'); - var $authorNameSpan = $('.author-name-span'); + let $selectAuthor = $('#AuthorSelect'); + let $authorNameSpan = $('.author-name-span'); $selectAuthor.on('change', function () { - var authorId = $selectAuthor.val(); + let authorId = $selectAuthor.val(); reloadPageWithQueryString({'authorId': authorId}); }); $authorNameSpan.click(function () { - var authorId = $(this).data('author-id'); + let authorId = $(this).data('author-id'); reloadPageWithQueryString({'authorId': authorId}); }); diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Volo.CmsKit.Public.Web.csproj b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Volo.CmsKit.Public.Web.csproj index da794f2eac..9953a9a2d7 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Volo.CmsKit.Public.Web.csproj +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Volo.CmsKit.Public.Web.csproj @@ -35,4 +35,8 @@ + + + + From e05eef2f65f0de27ebef5b095591b143b713414d Mon Sep 17 00:00:00 2001 From: malik masis Date: Tue, 6 Dec 2022 15:52:00 +0300 Subject: [PATCH 04/22] updated language --- .../Volo/CmsKit/Localization/Resources/en.json | 3 ++- .../Volo/CmsKit/Localization/Resources/tr.json | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) 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 19e5de70af..a5fa44e2be 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 @@ -209,6 +209,7 @@ "Feature:ReactionEnable": "Reaction", "Feature:ReactionEnableDescription": "CMS Kit's reaction system that allows users to send reactions to entities such as BlogPost, Comments, etc.", "Feature:TagEnable": "Taging", - "Feature:TagEnableDescription": "CMS Kit's tag system that allows tagging entities such as BlogPost." + "Feature:TagEnableDescription": "CMS Kit's tag system that allows tagging entities such as BlogPost.", + "DeleteBlogPostMessage": "The blog will be deleted. Are you sure?" } } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json index a93e8b3f1c..a7e2e4702f 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json @@ -209,6 +209,7 @@ "Feature:ReactionEnable": "Reaksiyon", "Feature:ReactionEnableDescription": "Cmskit reaksiyon sistemi", "Feature:TagEnable": "Etkiket", - "Feature:TagEnableDescription": "Cmskit etiket sistemi" + "Feature:TagEnableDescription": "Cmskit etiket sistemi", + "DeleteBlogPostMessage": "Blog silinecek. Emin misiniz?" } } From 74dd5aab997946ff2c2ffa28f2d380581afbe526 Mon Sep 17 00:00:00 2001 From: malik masis Date: Wed, 7 Dec 2022 11:59:26 +0300 Subject: [PATCH 05/22] Update cms-kit-generate-proxy.json --- .../ClientProxies/cms-kit-generate-proxy.json | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/cms-kit-generate-proxy.json b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/cms-kit-generate-proxy.json index 2892c636e3..d5c6133c40 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/cms-kit-generate-proxy.json +++ b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/cms-kit-generate-proxy.json @@ -1169,6 +1169,43 @@ }, "allowAnonymous": null, "implementFrom": "Volo.CmsKit.Public.Blogs.IBlogPostPublicAppService" + }, + "DeleteAsyncById": { + "uniqueName": "DeleteAsyncById", + "name": "DeleteAsync", + "httpMethod": "DELETE", + "url": "api/cms-kit-public/blog-posts/{id}", + "supportedVersions": [], + "parametersOnMethod": [ + { + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + } + ], + "parameters": [ + { + "nameOnMethod": "id", + "name": "id", + "jsonName": null, + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": [], + "bindingSourceId": "Path", + "descriptorName": "" + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + }, + "allowAnonymous": null, + "implementFrom": "Volo.CmsKit.Public.Blogs.IBlogPostPublicAppService" } } } From 6159aae526f08603743472a66c7f7efb78e43f74 Mon Sep 17 00:00:00 2001 From: malik masis Date: Wed, 7 Dec 2022 11:59:53 +0300 Subject: [PATCH 06/22] Added classes for captcha --- .../Security/VoloCaptcha/CaptchaException.cs | 10 + .../Security/VoloCaptcha/CaptchaOptions.cs | 67 +++++++ .../Security/VoloCaptcha/CaptchaOutput.cs | 32 ++++ .../Volo/Security/VoloCaptcha/EncoderTypes.cs | 7 + .../VoloCaptcha/RandomTextGenerator.cs | 73 ++++++++ .../SimpleMathsCaptchaGenerator.cs | 175 ++++++++++++++++++ 6 files changed, 364 insertions(+) create mode 100644 modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaException.cs create mode 100644 modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaOptions.cs create mode 100644 modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaOutput.cs create mode 100644 modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/EncoderTypes.cs create mode 100644 modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/RandomTextGenerator.cs create mode 100644 modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/SimpleMathsCaptchaGenerator.cs diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaException.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaException.cs new file mode 100644 index 0000000000..60b2b8442f --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaException.cs @@ -0,0 +1,10 @@ +using System; + +namespace Volo.CmsKit.Public.Application.Security.VoloCaptcha; + +public class CaptchaException : Exception +{ + public CaptchaException(string message) : base(message) + { + } +} \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaOptions.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaOptions.cs new file mode 100644 index 0000000000..33811f25f2 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaOptions.cs @@ -0,0 +1,67 @@ +using SixLabors.Fonts; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Formats; + +namespace Volo.CmsKit.Public.Application.Security.VoloCaptcha; + +public class CaptchaOptions +{ + /// + /// Default fonts are "Arial", "Verdana", "Times New Roman" in Windows. These fonts must exist in the target OS. + /// + public string[] FontFamilies { get; set; } = new string[] { "Arial", "Verdana", "Times New Roman" }; + + public Color[] TextColor { get; set; } = new Color[] + { + Color.Blue, Color.Black, Color.Black, Color.Brown, Color.Gray, Color.Green + }; + public Color[] DrawLinesColor { get; set; } = new Color[] + { + Color.Blue, Color.Black, Color.Black, Color.Brown, Color.Gray, Color.Green + }; + + public float MinLineThickness { get; set; } = 0.7f; + + public float MaxLineThickness { get; set; } = 2.0f; + + public ushort Width { get; set; } = 180; + + public ushort Height { get; set; } = 70; + + public ushort NoiseRate { get; set; } = 500; + + public Color[] NoiseRateColor { get; set; } = new Color[] { Color.Gray }; + + public byte FontSize { get; set; } = 32; + + public FontStyle FontStyle { get; set; } = FontStyle.Regular; + + public EncoderTypes EncoderType { get; set; } = EncoderTypes.Png; + + public IImageEncoder Encoder => RandomTextGenerator.GetEncoder(EncoderType); + + public byte DrawLines { get; set; } = 2; + + public byte MaxRotationDegrees { get; set; } = 4; + + public int Number1MinValue { get; set; } = 1; + + public int Number1MaxValue { get; set; } = 99; + + public int Number2MinValue { get; set; } = 1; + + public int Number2MaxValue { get; set; } = 99; + + public CaptchaOptions() + { + + } + + public CaptchaOptions(int number1MinValue, int number1MaxValue, int number2MinValue, int number2MaxValue) + { + Number1MinValue = number1MinValue; + Number1MaxValue = number1MaxValue; + Number2MinValue = number2MinValue; + Number1MaxValue = number2MaxValue; + } +} \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaOutput.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaOutput.cs new file mode 100644 index 0000000000..10ddd2e78a --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaOutput.cs @@ -0,0 +1,32 @@ +using System; + +namespace Volo.CmsKit.Public.Application.Security.VoloCaptcha; + +public class CaptchaOutput +{ + public Guid Id { get; set; } + public string Text { get; set; } + public byte[] ImageBytes { get; set; } + public int Result { get; set; } +} + +public class CaptchaInput +{ + public int Number1 { get; set; } + public int Number2 { get; set; } +} + +public class CaptchaRequest +{ + public CaptchaInput Input { get; set; } + public CaptchaOutput Output { get; set; } + + public CaptchaRequest() + { + Input = new CaptchaInput(); + Output = new CaptchaOutput + { + Id = Guid.NewGuid() + }; + } +} \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/EncoderTypes.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/EncoderTypes.cs new file mode 100644 index 0000000000..8016903ba4 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/EncoderTypes.cs @@ -0,0 +1,7 @@ +namespace Volo.CmsKit.Public.Application.Security.VoloCaptcha; + +public enum EncoderTypes +{ + Jpeg, + Png, +} \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/RandomTextGenerator.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/RandomTextGenerator.cs new file mode 100644 index 0000000000..cf7d61bda8 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/RandomTextGenerator.cs @@ -0,0 +1,73 @@ +using System; +using System.Security.Cryptography; +using System.Text; +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Formats.Jpeg; +using SixLabors.ImageSharp.Formats.Png; + +namespace Volo.CmsKit.Public.Application.Security.VoloCaptcha; +public static class RandomTextGenerator +{ + private static readonly char[] AllowedChars = "abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVXYZW23456789".ToCharArray(); + + public static IImageEncoder GetEncoder(EncoderTypes encoderType) + { + IImageEncoder encoder = encoderType switch + { + EncoderTypes.Png => new PngEncoder(), + EncoderTypes.Jpeg => new JpegEncoder(), + _ => throw new ArgumentException($"Encoder '{encoderType}' not found!") + }; + + return encoder; + } + + public static string GetRandomText(int size) + { + var data = new byte[4 * size]; + using (var crypto = new RNGCryptoServiceProvider()) + { + crypto.GetBytes(data); + } + + var result = new StringBuilder(size); + for (var i = 0; i < size; i++) + { + var rnd = BitConverter.ToUInt32(data, i * 4); + var idx = rnd % AllowedChars.Length; + result.Append(AllowedChars[idx]); + } + + return result.ToString(); + } + + public static string GetUniqueKey(int size, char[] chars) + { + var data = new byte[4 * size]; + using (var crypto = new RNGCryptoServiceProvider()) + { + crypto.GetBytes(data); + } + + var result = new StringBuilder(size); + + for (var i = 0; i < size; i++) + { + var rnd = BitConverter.ToUInt32(data, i * 4); + var idx = rnd % chars.Length; + result.Append(chars[idx]); + } + + return result.ToString(); + } + + public static float GenerateNextFloat(double min = -3.40282347E+38, double max = 3.40282347E+38) + { + var random = new Random(); + var range = max - min; + var sample = random.NextDouble(); + var scaled = sample * range + min; + var result = (float)scaled; + return result; + } +} diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/SimpleMathsCaptchaGenerator.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/SimpleMathsCaptchaGenerator.cs new file mode 100644 index 0000000000..595426658a --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/SimpleMathsCaptchaGenerator.cs @@ -0,0 +1,175 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Numerics; +using System.Threading.Tasks; +using SixLabors.Fonts; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Drawing.Processing; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using Volo.Abp.DependencyInjection; +using Color = SixLabors.ImageSharp.Color; +using PointF = SixLabors.ImageSharp.PointF; + +namespace Volo.CmsKit.Public.Application.Security.VoloCaptcha; + +public class SimpleMathsCaptchaGenerator : ISingletonDependency +{ + private static Dictionary Session { get; set; } = new Dictionary(); + + public CaptchaOutput Generate() + { + return Generate(options: null, number1: null, number2: null); + } + + public CaptchaOutput Generate(CaptchaOptions options) + { + return Generate(options, number1: null, number2: null); + } + + /// + /// Creates a simple captcha code. + /// + /// Options for captcha generation + /// First number for maths operation + /// Second number for maths operation + /// + public CaptchaOutput Generate(CaptchaOptions options, int? number1, int? number2) + { + var random = new Random(); + options ??= new CaptchaOptions(); + + number1 ??= random.Next(options.Number1MinValue, options.Number1MaxValue); + number2 ??= random.Next(options.Number2MinValue, options.Number2MaxValue); + + var text = number1 + "+" + number2; + var request = new CaptchaRequest + { + Input = + { + Number1 = number1.Value, + Number2 = number2.Value + }, + Output = + { + Text = text, + Result = Calculate(number1.Value, number2.Value), + ImageBytes = GenerateInternal(text, options) + } + }; + + Session[request.Output.Id] = request; + return request.Output; + } + + private static int Calculate(int number1, int number2) + { + return number1 + number2; + } + + public void Validate(Guid requestId, int value) + { + var request = Session[requestId]; + if (request.Output.Result != value) + { + throw new CaptchaException("The captcha code doesn't match text on the picture! Please try again."); + } + } + + public void Validate(Guid requestId, string value) + { + if (int.TryParse(value, out var captchaInput)) + { + Validate(requestId, captchaInput); + } + else + { + throw new CaptchaException("The captcha code is missing!"); + } + } + + private byte[] GenerateInternal(string stringText, CaptchaOptions options) + { + byte[] result; + + using (var image = new Image(options.Width, options.Height)) + { + float position = 0; + var random = new Random(); + var startWith = (byte)random.Next(5, 10); + image.Mutate(ctx => ctx.BackgroundColor(Color.Transparent)); + var fontName = options.FontFamilies[random.Next(0, options.FontFamilies.Length)]; + var font = SystemFonts.CreateFont(fontName, options.FontSize, options.FontStyle); + + foreach (var character in stringText) + { + var text = character.ToString(); + var color = options.TextColor[random.Next(0, options.TextColor.Length)]; + var location = new PointF(startWith + position, random.Next(6, 13)); + image.Mutate(ctx => ctx.DrawText(text, font, color, location)); + position += TextMeasurer.Measure(character.ToString(), new RendererOptions(font, location)).Width; + } + + //add rotation + var rotation = GetRotation(options); + image.Mutate(ctx => ctx.Transform(rotation)); + + // add the dynamic image to original image + var size = (ushort)TextMeasurer.Measure(stringText, new RendererOptions(font)).Width; + var img = new Image(size + 15, options.Height); + img.Mutate(ctx => ctx.BackgroundColor(Color.White)); + + Parallel.For(0, options.DrawLines, i => + { + var x0 = random.Next(0, random.Next(0, 30)); + var y0 = random.Next(10, img.Height); + + var x1 = random.Next(30, img.Width); + var y1 = random.Next(0, img.Height); + + img.Mutate(ctx => + ctx.DrawLines(options.TextColor[random.Next(0, options.TextColor.Length)], + RandomTextGenerator.GenerateNextFloat(options.MinLineThickness, options.MaxLineThickness), + new PointF[] { new PointF(x0, y0), new PointF(x1, y1) }) + ); + }); + + img.Mutate(ctx => ctx.DrawImage(image, 0.80f)); + + Parallel.For(0, options.NoiseRate, i => + { + var x0 = random.Next(0, img.Width); + var y0 = random.Next(0, img.Height); + img.Mutate( + ctx => ctx + .DrawLines(options.NoiseRateColor[random.Next(0, options.NoiseRateColor.Length)], + RandomTextGenerator.GenerateNextFloat(0.5, 1.5), new PointF[] { new Vector2(x0, y0), new Vector2(x0, y0) }) + ); + }); + + img.Mutate(x => + { + x.Resize(options.Width, options.Height); + }); + + using (var ms = new MemoryStream()) + { + img.Save(ms, options.Encoder); + result = ms.ToArray(); + } + } + + return result; + } + + private static AffineTransformBuilder GetRotation(CaptchaOptions options) + { + var random = new Random(); + var width = random.Next(10, options.Width); + var height = random.Next(10, options.Height); + var pointF = new PointF(width, height); + var rotationDegrees = random.Next(0, options.MaxRotationDegrees); + return new AffineTransformBuilder().PrependRotationDegrees(rotationDegrees, pointF); + } +} \ No newline at end of file From ac99df4bd90a860af3814e191473d99522c835da Mon Sep 17 00:00:00 2001 From: malik masis Date: Wed, 7 Dec 2022 12:01:14 +0300 Subject: [PATCH 07/22] Updated the backend side --- .../CmsKit/Public/Comments/CreateCommentInput.cs | 4 ++++ .../Volo.CmsKit.Public.Application.csproj | 4 +++- .../Public/Comments/CommentPublicAppService.cs | 14 +++++++++++++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Comments/CreateCommentInput.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Comments/CreateCommentInput.cs index 6ae524f0f2..c0eae8650e 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Comments/CreateCommentInput.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Comments/CreateCommentInput.cs @@ -13,4 +13,8 @@ public class CreateCommentInput public string Text { get; set; } public Guid? RepliedCommentId { get; set; } + + public Guid? CaptchaToken { get; set; } + + public int CaptchaAnswer { get; set; } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo.CmsKit.Public.Application.csproj b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo.CmsKit.Public.Application.csproj index 9f6d08fea6..b092c3f511 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo.CmsKit.Public.Application.csproj +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo.CmsKit.Public.Application.csproj @@ -1,4 +1,4 @@ - + @@ -9,6 +9,8 @@ + + diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Comments/CommentPublicAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Comments/CommentPublicAppService.cs index ef7e6be9fd..ecd7bb294d 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Comments/CommentPublicAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Comments/CommentPublicAppService.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; +using SixLabors.ImageSharp.Formats.Gif; +using Volo.Abp; using Volo.Abp.Application.Dtos; using Volo.Abp.Authorization; using Volo.Abp.Data; @@ -13,6 +15,7 @@ using Volo.Abp.Users; using Volo.CmsKit.Comments; using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; +using Volo.CmsKit.Public.Application.Security.VoloCaptcha; using Volo.CmsKit.Users; namespace Volo.CmsKit.Public.Comments; @@ -26,16 +29,20 @@ public class CommentPublicAppService : CmsKitPublicAppServiceBase, ICommentPubli public IDistributedEventBus DistributedEventBus { get; } protected CommentManager CommentManager { get; } + public SimpleMathsCaptchaGenerator SimpleMathsCaptchaGenerator { get; } + public CommentPublicAppService( ICommentRepository commentRepository, ICmsUserLookupService cmsUserLookupService, IDistributedEventBus distributedEventBus, - CommentManager commentManager) + CommentManager commentManager, + SimpleMathsCaptchaGenerator simpleMathsCaptchaGenerator) { CommentRepository = commentRepository; CmsUserLookupService = cmsUserLookupService; DistributedEventBus = distributedEventBus; CommentManager = commentManager; + SimpleMathsCaptchaGenerator = simpleMathsCaptchaGenerator; } public virtual async Task> GetListAsync(string entityType, string entityId) @@ -51,6 +58,11 @@ public class CommentPublicAppService : CmsKitPublicAppServiceBase, ICommentPubli [Authorize] public virtual async Task CreateAsync(string entityType, string entityId, CreateCommentInput input) { + if (input.RepliedCommentId.HasValue) + { + SimpleMathsCaptchaGenerator.Validate(input.CaptchaToken.Value, input.CaptchaAnswer); + } + var user = await CmsUserLookupService.GetByIdAsync(CurrentUser.GetId()); if (input.RepliedCommentId.HasValue) From 4ff130d570d69502c8e178f252bab478d8955ee4 Mon Sep 17 00:00:00 2001 From: malik masis Date: Wed, 7 Dec 2022 12:02:06 +0300 Subject: [PATCH 08/22] updated the ui side --- .../Commenting/CommentingViewComponent.cs | 47 +++++++++++++-- .../Components/Commenting/Default.cshtml | 47 ++++++++++----- .../Shared/Components/Commenting/default.css | 26 +++++++- .../Shared/Components/Commenting/default.js | 59 ++++++++++--------- .../Shared/Components/Commenting/default.scss | 30 ++++++++++ 5 files changed, 161 insertions(+), 48 deletions(-) create mode 100644 modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.scss diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/CommentingViewComponent.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/CommentingViewComponent.cs index 81fd94406d..eb05b77926 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/CommentingViewComponent.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/CommentingViewComponent.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; @@ -7,6 +8,7 @@ using Microsoft.Extensions.Options; using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc.UI; using Volo.Abp.AspNetCore.Mvc.UI.Widgets; +using Volo.CmsKit.Public.Application.Security.VoloCaptcha; using Volo.CmsKit.Public.Comments; using Volo.CmsKit.Web.Renderers; @@ -24,15 +26,31 @@ public class CommentingViewComponent : AbpViewComponent public ICommentPublicAppService CommentPublicAppService { get; } public IMarkdownToHtmlRenderer MarkdownToHtmlRenderer { get; } public AbpMvcUiOptions AbpMvcUiOptions { get; } + public SimpleMathsCaptchaGenerator SimpleMathsCaptchaGenerator { get; } + + [HiddenInput] + [BindProperty] + public string RecaptchaToken { get; set; } + + [HiddenInput] + [BindProperty] + public Guid CaptchaId { get; set; } + + [BindProperty] + public CommentingViewModel Input { get; set; } + + public CaptchaOutput CaptchaOutput { get; set; } public CommentingViewComponent( ICommentPublicAppService commentPublicAppService, IOptions options, - IMarkdownToHtmlRenderer markdownToHtmlRenderer) + IMarkdownToHtmlRenderer markdownToHtmlRenderer, + SimpleMathsCaptchaGenerator simpleMathsCaptchaGenerator) { CommentPublicAppService = commentPublicAppService; MarkdownToHtmlRenderer = markdownToHtmlRenderer; AbpMvcUiOptions = options.Value; + SimpleMathsCaptchaGenerator = simpleMathsCaptchaGenerator; } public virtual async Task InvokeAsync( @@ -42,7 +60,6 @@ public class CommentingViewComponent : AbpViewComponent var comments = (await CommentPublicAppService .GetListAsync(entityType, entityId)).Items; - var loginUrl = $"{AbpMvcUiOptions.LoginUrl}?returnUrl={HttpContext.Request.Path.ToString()}&returnUrlHash=#cms-comment_{entityType}_{entityId}"; var viewModel = new CommentingViewModel @@ -52,10 +69,23 @@ public class CommentingViewComponent : AbpViewComponent LoginUrl = loginUrl, Comments = comments.OrderByDescending(i => i.CreationTime).ToList() }; - await ConvertMarkdownTextsToHtml(viewModel); - return View("~/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml", viewModel); + CaptchaOutput = SimpleMathsCaptchaGenerator.Generate(new CaptchaOptions( + number1MinValue: 1, + number1MaxValue: 10, + number2MinValue: 5, + number2MaxValue: 15) + ); + + viewModel.CaptchaImageBase64 = GetCaptchaImageBase64(CaptchaOutput.ImageBytes); + this.Input = viewModel; + return View("~/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml", this); + } + + private string GetCaptchaImageBase64(byte[] bytes) + { + return $"data:image/jpg;base64,{Convert.ToBase64String(bytes)}"; } private async Task ConvertMarkdownTextsToHtml(CommentingViewModel viewModel) @@ -86,6 +116,15 @@ public class CommentingViewComponent : AbpViewComponent public IReadOnlyList Comments { get; set; } public Dictionary RawCommentTexts { get; set; } + + [Required] + [StringLength(100, MinimumLength = 1)] + public string Captcha { get; set; } + + public string CaptchaImageBase64 { get; set; } + + + } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml index 9d0438098d..3814ef755f 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml @@ -11,7 +11,7 @@ @inject ICurrentUser CurrentUser @inject IOptionsSnapshot cmsKitUiOptions; @inject IHtmlLocalizer L -@model Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Commenting.CommentingViewComponent.CommentingViewModel +@model Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Commenting.CommentingViewComponent @{ Func GetCommentTitle(CmsUserDto author, DateTime creationTime) => @@ -36,9 +36,26 @@
+ + +
+ +
+
+ +
+
+ +
+ + +
+
+ +
- + @L["Send"] @if (cancelButton) @@ -71,13 +88,13 @@ { @if (CurrentUser.IsAuthenticated) { - + @L["Reply"] } else { - @L["LoginToReply"] + @L["LoginToReply"] } } @if (authorId == CurrentUser.Id) @@ -93,9 +110,10 @@ } @{ Func GetEditArea(Guid id, string text, string concurrencyStamp) => - @ }
+ diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.css b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.css index 469c8274f6..8d241afcd5 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.css +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.css @@ -3,4 +3,28 @@ } .comment-links:hover { text-decoration: none; -} \ No newline at end of file +} +body .volo-captcha img { + border: 1px outset #dddcdc; + border-radius: 4px; + height: 45px; +} + +body .volo-captcha .d-flex .form-group { + width: 100%; +} + +@media (max-width: 800px) { + body .volo-captcha #Input_Captcha { + margin-left: 0px; + } +} + +body .form-control { + border: 1px outset #e3e3e3 !important; + padding: 10px !important; +} + +body #submit-button { + margin-top: 10px; +} diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js index a4fca33947..3b98f1f7ec 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js @@ -1,10 +1,10 @@ (function ($) { - var l = abp.localization.getResource('CmsKit'); + let l = abp.localization.getResource('CmsKit'); abp.widgets.CmsCommenting = function ($widget) { - var widgetManager = $widget.data('abp-widget-manager'); - var $commentArea = $widget.find('.cms-comment-area'); + let widgetManager = $widget.data('abp-widget-manager'); + let $commentArea = $widget.find('.cms-comment-area'); function getFilters() { return { @@ -15,14 +15,14 @@ function registerEditLinks($container) { $container.find('.comment-edit-link').each(function () { - var $link = $(this); + let $link = $(this); $link.on('click', function (e) { e.preventDefault(); - var commentId = $link.data('id'); + let commentId = $link.data('id'); - var $relatedCommentContentArea = $container.find('.cms-comment-content-area[data-id=' + commentId + ']'); - var $relatedCommentEditFormArea = $container.find('.cms-comment-edit-area[data-id=' + commentId + ']'); + let $relatedCommentContentArea = $container.find('.cms-comment-content-area[data-id=' + commentId + ']'); + let $relatedCommentEditFormArea = $container.find('.cms-comment-edit-area[data-id=' + commentId + ']'); $relatedCommentContentArea.hide(); $relatedCommentEditFormArea.show(); @@ -30,15 +30,15 @@ }); }); $container.find('.comment-edit-cancel-button').each(function () { - var $button = $(this); + let $button = $(this); $button.on('click', function (e) { e.preventDefault(); - var commentId = $button.data('id'); + let commentId = $button.data('id'); - var $relatedCommentContentArea = $container.find('.cms-comment-content-area[data-id=' + commentId + ']'); - var $relatedCommentEditFormArea = $container.find('.cms-comment-edit-area[data-id=' + commentId + ']'); - var $link = $container.find('.comment-edit-link[data-id=' + commentId + ']'); + let $relatedCommentContentArea = $container.find('.cms-comment-content-area[data-id=' + commentId + ']'); + let $relatedCommentEditFormArea = $container.find('.cms-comment-edit-area[data-id=' + commentId + ']'); + let $link = $container.find('.comment-edit-link[data-id=' + commentId + ']'); $relatedCommentContentArea.show(); $relatedCommentEditFormArea.hide(); @@ -49,14 +49,14 @@ function registerReplyLinks($container) { $container.find('.comment-reply-link').each(function () { - var $link = $(this); + let $link = $(this); $link.on('click', function (e) { e.preventDefault(); - var replyCommentId = $link.data('reply-id'); + let replyCommentId = $link.data('reply-id'); - var $relatedCommentArea = $container.find('.cms-comment-form-area[data-reply-id=' + replyCommentId + ']'); - var $links = $container.find('.comment-reply-link[data-reply-id=' + replyCommentId + ']'); + let $relatedCommentArea = $container.find('.cms-comment-form-area[data-reply-id=' + replyCommentId + ']'); + let $links = $container.find('.comment-reply-link[data-reply-id=' + replyCommentId + ']'); $relatedCommentArea.show(); $relatedCommentArea.find('textarea').focus(); @@ -64,14 +64,14 @@ }); }); $container.find('.reply-cancel-button').each(function () { - var $button = $(this); + let $button = $(this); $button.on('click', function (e) { e.preventDefault(); - var replyCommentId = $button.data('reply-id'); + let replyCommentId = $button.data('reply-id'); - var $relatedCommentArea = $container.find('.cms-comment-form-area[data-reply-id=' + replyCommentId + ']'); - var $links = $container.find('.comment-reply-link[data-reply-id=' + replyCommentId + ']'); + let $relatedCommentArea = $container.find('.cms-comment-form-area[data-reply-id=' + replyCommentId + ']'); + let $links = $container.find('.comment-reply-link[data-reply-id=' + replyCommentId + ']'); $relatedCommentArea.hide(); $links.removeClass('disabled'); @@ -81,7 +81,7 @@ function registerDeleteLinks($container) { $container.find('.comment-delete-link').each(function () { - var $link = $(this); + let $link = $(this); $link.on('click', '', function (e) { e.preventDefault(); @@ -99,10 +99,10 @@ function registerUpdateOfNewComment($container) { $container.find('.cms-comment-update-form').each(function () { - var $form = $(this); + let $form = $(this); $form.submit(function (e) { e.preventDefault(); - var formAsObject = $form.serializeFormToObject(); + let formAsObject = $form.serializeFormToObject(); volo.cmsKit.public.comments.commentPublic.update( formAsObject.id, { @@ -118,21 +118,22 @@ function registerSubmissionOfNewComment($container) { $container.find('.cms-comment-form').each(function () { - var $form = $(this); + let $form = $(this); $form.submit(function (e) { e.preventDefault(); - var formAsObject = $form.serializeFormToObject(); + let formAsObject = $form.serializeFormToObject(); - if (formAsObject.repliedCommentId == ''){ + if (formAsObject.repliedCommentId == '') { formAsObject.repliedCommentId = null; } - volo.cmsKit.public.comments.commentPublic.create( $commentArea.attr('data-entity-type'), $commentArea.attr('data-entity-id'), { repliedCommentId: formAsObject.repliedCommentId, - text: formAsObject.commentText + text: formAsObject.commentText, + captchaToken: formAsObject.captchaId, + captchaAnswer: formAsObject.input.captcha } ).then(function () { widgetManager.refresh($widget); @@ -146,7 +147,7 @@ return; } - var $link = $(location.hash + '_link'); + let $link = $(location.hash + '_link'); if ($link.length > 0) { $link.click(); diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.scss b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.scss new file mode 100644 index 0000000000..82d41f9795 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.scss @@ -0,0 +1,30 @@ +body { + .volo-captcha { + img { + border: 1px outset #dddcdc; + border-radius: 4px; + height: 45px; + } + + .d-flex { + .form-group { + width: 100%; + } + } + + @media (max-width: 800px) { + #Input_Captcha { + margin-left: 0px; + } + } + } + + .form-control { + border: 1px outset #e3e3e3 !important; + padding: 10px !important; + } + + #submit-button { + margin-top: 10px; + } +} From 88b9483cc0f8695582c24d13be18091291a80362 Mon Sep 17 00:00:00 2001 From: malik masis Date: Wed, 7 Dec 2022 12:02:28 +0300 Subject: [PATCH 09/22] updated proxy --- .../ClientProxies/BlogPostPublicClientProxy.Generated.cs | 8 ++++++++ .../Volo.CmsKit.Public.Web/Volo.CmsKit.Public.Web.csproj | 8 +++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/BlogPostPublicClientProxy.Generated.cs b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/BlogPostPublicClientProxy.Generated.cs index 79b883aa49..9fc813e899 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/BlogPostPublicClientProxy.Generated.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/BlogPostPublicClientProxy.Generated.cs @@ -50,4 +50,12 @@ public partial class BlogPostPublicClientProxy : ClientProxyBase - + + + @@ -35,8 +37,4 @@ - - - - From d496d3b62d7ef6e346c65326a95881cde40d5264 Mon Sep 17 00:00:00 2001 From: malik masis Date: Wed, 7 Dec 2022 14:02:34 +0300 Subject: [PATCH 10/22] Added null check --- .../Pages/CmsKit/Shared/Components/Commenting/default.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js index 3b98f1f7ec..7c4b86712e 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js @@ -126,6 +126,7 @@ if (formAsObject.repliedCommentId == '') { formAsObject.repliedCommentId = null; } + volo.cmsKit.public.comments.commentPublic.create( $commentArea.attr('data-entity-type'), $commentArea.attr('data-entity-id'), @@ -133,7 +134,7 @@ repliedCommentId: formAsObject.repliedCommentId, text: formAsObject.commentText, captchaToken: formAsObject.captchaId, - captchaAnswer: formAsObject.input.captcha + captchaAnswer: formAsObject.input?.captcha } ).then(function () { widgetManager.refresh($widget); From 111921cf926bb76a44bbb3df59399e90539e5d91 Mon Sep 17 00:00:00 2001 From: malik masis Date: Wed, 7 Dec 2022 14:03:47 +0300 Subject: [PATCH 11/22] Added IsRecaptchaEnabled to CmsKitCommentOptions --- .../CmsKitWebUnifiedModule.cs | 1 + .../CmsKit/Comments/CmsKitCommentOptions.cs | 6 ++++ .../Comments/CommentPublicAppService.cs | 7 +++-- .../Commenting/CommentingViewComponent.cs | 23 +++++++++----- .../Components/Commenting/Default.cshtml | 30 ++++++++++--------- 5 files changed, 43 insertions(+), 24 deletions(-) diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs index 0343a3bc58..763218edc4 100644 --- a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs @@ -167,6 +167,7 @@ public class CmsKitWebUnifiedModule : AbpModule Configure(options => { options.EntityTypes.Add(new CommentEntityTypeDefinition("quote")); + options.IsRecaptchaEnabled = true; }); Configure(options => diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/CmsKitCommentOptions.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/CmsKitCommentOptions.cs index ca8476073c..94d3b785ec 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/CmsKitCommentOptions.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/CmsKitCommentOptions.cs @@ -7,4 +7,10 @@ public class CmsKitCommentOptions { [NotNull] public List EntityTypes { get; } = new List(); + + /// + /// Flag to enable/disable ReCaptcha for comment component. + /// Default: false + /// + public bool IsRecaptchaEnabled { get; set; } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Comments/CommentPublicAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Comments/CommentPublicAppService.cs index ecd7bb294d..03665d19f9 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Comments/CommentPublicAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Comments/CommentPublicAppService.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; +using Microsoft.Extensions.Options; using SixLabors.ImageSharp.Formats.Gif; using Volo.Abp; using Volo.Abp.Application.Dtos; @@ -28,7 +29,7 @@ public class CommentPublicAppService : CmsKitPublicAppServiceBase, ICommentPubli protected ICmsUserLookupService CmsUserLookupService { get; } public IDistributedEventBus DistributedEventBus { get; } protected CommentManager CommentManager { get; } - + protected CmsKitCommentOptions CmsKitCommentOptions { get; } public SimpleMathsCaptchaGenerator SimpleMathsCaptchaGenerator { get; } public CommentPublicAppService( @@ -36,12 +37,14 @@ public class CommentPublicAppService : CmsKitPublicAppServiceBase, ICommentPubli ICmsUserLookupService cmsUserLookupService, IDistributedEventBus distributedEventBus, CommentManager commentManager, + IOptions cmsKitCommentOptions, SimpleMathsCaptchaGenerator simpleMathsCaptchaGenerator) { CommentRepository = commentRepository; CmsUserLookupService = cmsUserLookupService; DistributedEventBus = distributedEventBus; CommentManager = commentManager; + CmsKitCommentOptions = cmsKitCommentOptions.Value; SimpleMathsCaptchaGenerator = simpleMathsCaptchaGenerator; } @@ -58,7 +61,7 @@ public class CommentPublicAppService : CmsKitPublicAppServiceBase, ICommentPubli [Authorize] public virtual async Task CreateAsync(string entityType, string entityId, CreateCommentInput input) { - if (input.RepliedCommentId.HasValue) + if (CmsKitCommentOptions.IsRecaptchaEnabled && input.CaptchaToken.HasValue) { SimpleMathsCaptchaGenerator.Validate(input.CaptchaToken.Value, input.CaptchaAnswer); } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/CommentingViewComponent.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/CommentingViewComponent.cs index eb05b77926..6e1db54a5b 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/CommentingViewComponent.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/CommentingViewComponent.cs @@ -8,6 +8,7 @@ using Microsoft.Extensions.Options; using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc.UI; using Volo.Abp.AspNetCore.Mvc.UI.Widgets; +using Volo.CmsKit.Comments; using Volo.CmsKit.Public.Application.Security.VoloCaptcha; using Volo.CmsKit.Public.Comments; using Volo.CmsKit.Web.Renderers; @@ -26,6 +27,7 @@ public class CommentingViewComponent : AbpViewComponent public ICommentPublicAppService CommentPublicAppService { get; } public IMarkdownToHtmlRenderer MarkdownToHtmlRenderer { get; } public AbpMvcUiOptions AbpMvcUiOptions { get; } + public CmsKitCommentOptions CmsKitCommentOptions { get; } public SimpleMathsCaptchaGenerator SimpleMathsCaptchaGenerator { get; } [HiddenInput] @@ -45,11 +47,13 @@ public class CommentingViewComponent : AbpViewComponent ICommentPublicAppService commentPublicAppService, IOptions options, IMarkdownToHtmlRenderer markdownToHtmlRenderer, + IOptions cmsKitCommentOptions, SimpleMathsCaptchaGenerator simpleMathsCaptchaGenerator) { CommentPublicAppService = commentPublicAppService; MarkdownToHtmlRenderer = markdownToHtmlRenderer; AbpMvcUiOptions = options.Value; + CmsKitCommentOptions = cmsKitCommentOptions.Value; SimpleMathsCaptchaGenerator = simpleMathsCaptchaGenerator; } @@ -71,14 +75,17 @@ public class CommentingViewComponent : AbpViewComponent }; await ConvertMarkdownTextsToHtml(viewModel); - CaptchaOutput = SimpleMathsCaptchaGenerator.Generate(new CaptchaOptions( - number1MinValue: 1, - number1MaxValue: 10, - number2MinValue: 5, - number2MaxValue: 15) - ); - - viewModel.CaptchaImageBase64 = GetCaptchaImageBase64(CaptchaOutput.ImageBytes); + if (CmsKitCommentOptions.IsRecaptchaEnabled) + { + CaptchaOutput = SimpleMathsCaptchaGenerator.Generate(new CaptchaOptions( + number1MinValue: 1, + number1MaxValue: 10, + number2MinValue: 5, + number2MaxValue: 15) + ); + + viewModel.CaptchaImageBase64 = GetCaptchaImageBase64(CaptchaOutput.ImageBytes); + } this.Input = viewModel; return View("~/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml", this); } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml index 3814ef755f..9324eeb40b 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml @@ -3,6 +3,7 @@ @using Microsoft.Extensions.Options @using Volo.Abp.GlobalFeatures @using Volo.Abp.Users +@using Volo.CmsKit.Comments; @using Volo.CmsKit.GlobalFeatures @using Volo.CmsKit.Localization @using Volo.CmsKit.Public.Comments @@ -10,6 +11,7 @@ @using Volo.CmsKit.Web @inject ICurrentUser CurrentUser @inject IOptionsSnapshot cmsKitUiOptions; +@inject IOptions CmsKitCommentOptions @inject IHtmlLocalizer L @model Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Commenting.CommentingViewComponent @@ -37,22 +39,22 @@
- -
- -
-
- -
-
- + @if (CmsKitCommentOptions.Value.IsRecaptchaEnabled) + { +
+ +
+
+ +
+
+ +
+ +
- -
-
- - + }
From 603d1511769be717b99e1ba35ba9c3a1d87cd56a Mon Sep 17 00:00:00 2001 From: malik masis Date: Wed, 7 Dec 2022 14:25:13 +0300 Subject: [PATCH 12/22] Checked the correct user to see the delete button --- .../Pages/Public/CmsKit/Blogs/BlogPost.cshtml | 17 ++++++++++------- .../Public/CmsKit/Blogs/BlogPost.cshtml.cs | 1 - 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml index 789890704d..485aa20ac3 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml @@ -1,6 +1,7 @@ @page @using Volo.Abp.Data +@using Volo.Abp.Users; @using Volo.CmsKit.Public.Blogs @using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Blogs.BlogPostComment @using Volo.CmsKit.Public.Web.Pages @@ -17,9 +18,9 @@ @model Volo.CmsKit.Public.Web.Pages.Public.CmsKit.Blogs.BlogPostModel +@inject ICurrentUser CurrentUser @inject IMarkdownToHtmlRenderer MarkdownRenderer - @{ string dummyImageSource = "https://dummyimage.com/1280x720/a3a3a3/fff.png?text=" + Model.ViewModel.Title; var isScrollIndexEnabled = GlobalFeatureManager.Instance.IsEnabled() && Model.BlogPostScrollIndexFeature?.IsEnabled == true; @@ -136,12 +137,14 @@
- - + @if (Model.ViewModel.Author.Id == CurrentUser.Id) + { + + } @if (isScrollIndexEnabled) {
diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml.cs index 87630f9bd0..a503ff0794 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml.cs @@ -1,7 +1,6 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Volo.Abp.GlobalFeatures; -using Volo.Abp.ObjectMapping; using Volo.CmsKit.Blogs; using Volo.CmsKit.Contents; using Volo.CmsKit.GlobalFeatures; From ed14c5c61ca2858872ec00bf16f53017717de6c6 Mon Sep 17 00:00:00 2001 From: malik masis Date: Thu, 8 Dec 2022 23:02:16 +0300 Subject: [PATCH 13/22] Inherited CaptchaException from UserFriendlyException --- .../Volo/Security/VoloCaptcha/CaptchaException.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaException.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaException.cs index 60b2b8442f..4d0362f5ee 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaException.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaException.cs @@ -1,10 +1,15 @@ -using System; +using System.Runtime.Serialization; +using Volo.Abp; namespace Volo.CmsKit.Public.Application.Security.VoloCaptcha; -public class CaptchaException : Exception +public class CaptchaException : UserFriendlyException { public CaptchaException(string message) : base(message) { } + + public CaptchaException(SerializationInfo serializationInfo, StreamingContext context) : base(serializationInfo, context) + { + } } \ No newline at end of file From fc6dae3c9e3a42dc28fac9639872cf6b2bd90d8b Mon Sep 17 00:00:00 2001 From: malik masis Date: Fri, 9 Dec 2022 14:45:09 +0300 Subject: [PATCH 14/22] Moved captcha from the app layer to web --- .../Volo.CmsKit.Public.Application.csproj | 2 - .../Security/Captcha/CaptchaException.cs | 15 ++ .../Security/Captcha/CaptchaOptions.cs | 66 +++++++ .../Security/Captcha/CaptchaOutput.cs | 32 ++++ .../Security/Captcha/EncoderTypes.cs | 7 + .../Security/Captcha/RandomTextGenerator.cs | 73 ++++++++ .../Captcha/SimpleMathsCaptchaGenerator.cs | 175 ++++++++++++++++++ .../Volo.CmsKit.Public.Web.csproj | 3 +- 8 files changed, 370 insertions(+), 3 deletions(-) create mode 100644 modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/CaptchaException.cs create mode 100644 modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/CaptchaOptions.cs create mode 100644 modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/CaptchaOutput.cs create mode 100644 modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/EncoderTypes.cs create mode 100644 modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/RandomTextGenerator.cs create mode 100644 modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/SimpleMathsCaptchaGenerator.cs diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo.CmsKit.Public.Application.csproj b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo.CmsKit.Public.Application.csproj index b092c3f511..c062ee451a 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo.CmsKit.Public.Application.csproj +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo.CmsKit.Public.Application.csproj @@ -9,8 +9,6 @@ - - diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/CaptchaException.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/CaptchaException.cs new file mode 100644 index 0000000000..7914e85b02 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/CaptchaException.cs @@ -0,0 +1,15 @@ +using System.Runtime.Serialization; +using Volo.Abp; + +namespace Volo.CmsKit.Public.Web.Security.Captcha; + +public class CaptchaException : UserFriendlyException +{ + public CaptchaException(string message) : base(message) + { + } + + public CaptchaException(SerializationInfo serializationInfo, StreamingContext context) : base(serializationInfo, context) + { + } +} \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/CaptchaOptions.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/CaptchaOptions.cs new file mode 100644 index 0000000000..3db5aa06b6 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/CaptchaOptions.cs @@ -0,0 +1,66 @@ +using SixLabors.Fonts; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Formats; + +namespace Volo.CmsKit.Public.Web.Security.Captcha; + +public class CaptchaOptions +{ + /// + /// Default fonts are "Arial", "Verdana", "Times New Roman" in Windows. These fonts must exist in the target OS. + /// + public string[] FontFamilies { get; set; } = new string[] { "Arial", "Verdana", "Times New Roman" }; + + public Color[] TextColor { get; set; } = new Color[] + { + Color.Blue, Color.Black, Color.Black, Color.Brown, Color.Gray, Color.Green + }; + public Color[] DrawLinesColor { get; set; } = new Color[] + { + Color.Blue, Color.Black, Color.Black, Color.Brown, Color.Gray, Color.Green + }; + + public float MinLineThickness { get; set; } = 0.7f; + + public float MaxLineThickness { get; set; } = 2.0f; + + public ushort Width { get; set; } = 180; + + public ushort Height { get; set; } = 70; + + public ushort NoiseRate { get; set; } = 500; + + public Color[] NoiseRateColor { get; set; } = new Color[] { Color.Gray }; + + public byte FontSize { get; set; } = 32; + + public FontStyle FontStyle { get; set; } = FontStyle.Regular; + + public EncoderTypes EncoderType { get; set; } = EncoderTypes.Png; + + public IImageEncoder Encoder => RandomTextGenerator.GetEncoder(EncoderType); + + public byte DrawLines { get; set; } = 2; + + public byte MaxRotationDegrees { get; set; } = 4; + + public int Number1MinValue { get; set; } = 1; + + public int Number1MaxValue { get; set; } = 99; + + public int Number2MinValue { get; set; } = 1; + + public int Number2MaxValue { get; set; } = 99; + + public CaptchaOptions() + { + + } + public CaptchaOptions(int number1MinValue, int number1MaxValue, int number2MinValue, int number2MaxValue) + { + Number1MinValue = number1MinValue; + Number1MaxValue = number1MaxValue; + Number2MinValue = number2MinValue; + Number1MaxValue = number2MaxValue; + } +} \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/CaptchaOutput.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/CaptchaOutput.cs new file mode 100644 index 0000000000..3a483aa46a --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/CaptchaOutput.cs @@ -0,0 +1,32 @@ +using System; + +namespace Volo.CmsKit.Public.Web.Security.Captcha; + +public class CaptchaOutput +{ + public Guid Id { get; set; } + public string Text { get; set; } + public byte[] ImageBytes { get; set; } + public int Result { get; set; } +} + +public class CaptchaInput +{ + public int Number1 { get; set; } + public int Number2 { get; set; } +} + +public class CaptchaRequest +{ + public CaptchaInput Input { get; set; } + public CaptchaOutput Output { get; set; } + + public CaptchaRequest() + { + Input = new CaptchaInput(); + Output = new CaptchaOutput + { + Id = Guid.NewGuid() + }; + } +} \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/EncoderTypes.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/EncoderTypes.cs new file mode 100644 index 0000000000..60308946f0 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/EncoderTypes.cs @@ -0,0 +1,7 @@ +namespace Volo.CmsKit.Public.Web.Security.Captcha; + +public enum EncoderTypes +{ + Jpeg, + Png, +} \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/RandomTextGenerator.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/RandomTextGenerator.cs new file mode 100644 index 0000000000..df5818f88c --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/RandomTextGenerator.cs @@ -0,0 +1,73 @@ +using System; +using System.Security.Cryptography; +using System.Text; +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Formats.Jpeg; +using SixLabors.ImageSharp.Formats.Png; + +namespace Volo.CmsKit.Public.Web.Security.Captcha; +public static class RandomTextGenerator +{ + private static readonly char[] AllowedChars = "abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVXYZW23456789".ToCharArray(); + + public static IImageEncoder GetEncoder(EncoderTypes encoderType) + { + IImageEncoder encoder = encoderType switch + { + EncoderTypes.Png => new PngEncoder(), + EncoderTypes.Jpeg => new JpegEncoder(), + _ => throw new ArgumentException($"Encoder '{encoderType}' not found!") + }; + + return encoder; + } + + public static string GetRandomText(int size) + { + var data = new byte[4 * size]; + using (var crypto = new RNGCryptoServiceProvider()) + { + crypto.GetBytes(data); + } + + var result = new StringBuilder(size); + for (var i = 0; i < size; i++) + { + var rnd = BitConverter.ToUInt32(data, i * 4); + var idx = rnd % AllowedChars.Length; + result.Append(AllowedChars[idx]); + } + + return result.ToString(); + } + + public static string GetUniqueKey(int size, char[] chars) + { + var data = new byte[4 * size]; + using (var crypto = new RNGCryptoServiceProvider()) + { + crypto.GetBytes(data); + } + + var result = new StringBuilder(size); + + for (var i = 0; i < size; i++) + { + var rnd = BitConverter.ToUInt32(data, i * 4); + var idx = rnd % chars.Length; + result.Append(chars[idx]); + } + + return result.ToString(); + } + + public static float GenerateNextFloat(double min = -3.40282347E+38, double max = 3.40282347E+38) + { + var random = new Random(); + var range = max - min; + var sample = random.NextDouble(); + var scaled = sample * range + min; + var result = (float)scaled; + return result; + } +} diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/SimpleMathsCaptchaGenerator.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/SimpleMathsCaptchaGenerator.cs new file mode 100644 index 0000000000..b9268a7f6a --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/SimpleMathsCaptchaGenerator.cs @@ -0,0 +1,175 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Numerics; +using System.Threading.Tasks; +using SixLabors.Fonts; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Drawing.Processing; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using Volo.Abp.DependencyInjection; +using Color = SixLabors.ImageSharp.Color; +using PointF = SixLabors.ImageSharp.PointF; + +namespace Volo.CmsKit.Public.Web.Security.Captcha; + +public class SimpleMathsCaptchaGenerator : ISingletonDependency +{ + private static Dictionary Session { get; set; } = new Dictionary(); + + public CaptchaOutput Generate() + { + return Generate(options: null, number1: null, number2: null); + } + + public CaptchaOutput Generate(CaptchaOptions options) + { + return Generate(options, number1: null, number2: null); + } + + /// + /// Creates a simple captcha code. + /// + /// Options for captcha generation + /// First number for maths operation + /// Second number for maths operation + /// + public CaptchaOutput Generate(CaptchaOptions options, int? number1, int? number2) + { + var random = new Random(); + options ??= new CaptchaOptions(); + + number1 ??= random.Next(options.Number1MinValue, options.Number1MaxValue); + number2 ??= random.Next(options.Number2MinValue, options.Number2MaxValue); + + var text = number1 + "+" + number2; + var request = new CaptchaRequest + { + Input = + { + Number1 = number1.Value, + Number2 = number2.Value + }, + Output = + { + Text = text, + Result = Calculate(number1.Value, number2.Value), + ImageBytes = GenerateInternal(text, options) + } + }; + + Session[request.Output.Id] = request; + return request.Output; + } + + private static int Calculate(int number1, int number2) + { + return number1 + number2; + } + + public void Validate(Guid requestId, int value) + { + var request = Session[requestId]; + if (request.Output.Result != value) + { + throw new CaptchaException("The captcha code doesn't match text on the picture! Please try again."); + } + } + + public void Validate(Guid requestId, string value) + { + if (int.TryParse(value, out var captchaInput)) + { + Validate(requestId, captchaInput); + } + else + { + throw new CaptchaException("The captcha code is missing!"); + } + } + + private byte[] GenerateInternal(string stringText, CaptchaOptions options) + { + byte[] result; + + using (var image = new Image(options.Width, options.Height)) + { + float position = 0; + var random = new Random(); + var startWith = (byte)random.Next(5, 10); + image.Mutate(ctx => ctx.BackgroundColor(Color.Transparent)); + var fontName = options.FontFamilies[random.Next(0, options.FontFamilies.Length)]; + var font = SystemFonts.CreateFont(fontName, options.FontSize, options.FontStyle); + + foreach (var character in stringText) + { + var text = character.ToString(); + var color = options.TextColor[random.Next(0, options.TextColor.Length)]; + var location = new PointF(startWith + position, random.Next(6, 13)); + image.Mutate(ctx => ctx.DrawText(text, font, color, location)); + position += TextMeasurer.Measure(character.ToString(), new RendererOptions(font, location)).Width; + } + + //add rotation + var rotation = GetRotation(options); + image.Mutate(ctx => ctx.Transform(rotation)); + + // add the dynamic image to original image + var size = (ushort)TextMeasurer.Measure(stringText, new RendererOptions(font)).Width; + var img = new Image(size + 15, options.Height); + img.Mutate(ctx => ctx.BackgroundColor(Color.White)); + + Parallel.For(0, options.DrawLines, i => + { + var x0 = random.Next(0, random.Next(0, 30)); + var y0 = random.Next(10, img.Height); + + var x1 = random.Next(30, img.Width); + var y1 = random.Next(0, img.Height); + + img.Mutate(ctx => + ctx.DrawLines(options.TextColor[random.Next(0, options.TextColor.Length)], + RandomTextGenerator.GenerateNextFloat(options.MinLineThickness, options.MaxLineThickness), + new PointF[] { new PointF(x0, y0), new PointF(x1, y1) }) + ); + }); + + img.Mutate(ctx => ctx.DrawImage(image, 0.80f)); + + Parallel.For(0, options.NoiseRate, i => + { + var x0 = random.Next(0, img.Width); + var y0 = random.Next(0, img.Height); + img.Mutate( + ctx => ctx + .DrawLines(options.NoiseRateColor[random.Next(0, options.NoiseRateColor.Length)], + RandomTextGenerator.GenerateNextFloat(0.5, 1.5), new PointF[] { new Vector2(x0, y0), new Vector2(x0, y0) }) + ); + }); + + img.Mutate(x => + { + x.Resize(options.Width, options.Height); + }); + + using (var ms = new MemoryStream()) + { + img.Save(ms, options.Encoder); + result = ms.ToArray(); + } + } + + return result; + } + + private static AffineTransformBuilder GetRotation(CaptchaOptions options) + { + var random = new Random(); + var width = random.Next(10, options.Width); + var height = random.Next(10, options.Height); + var pointF = new PointF(width, height); + var rotationDegrees = random.Next(0, options.MaxRotationDegrees); + return new AffineTransformBuilder().PrependRotationDegrees(rotationDegrees, pointF); + } +} \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Volo.CmsKit.Public.Web.csproj b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Volo.CmsKit.Public.Web.csproj index ce31515b0e..7aaa2eda5e 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Volo.CmsKit.Public.Web.csproj +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Volo.CmsKit.Public.Web.csproj @@ -15,10 +15,11 @@ - + + From 1e27ed668180cc852e58c7f91396ed0a97377b47 Mon Sep 17 00:00:00 2001 From: malik masis Date: Fri, 9 Dec 2022 14:48:18 +0300 Subject: [PATCH 15/22] Refactored the structure by removing from the app layer --- .../Comments/CommentPublicAppService.cs | 18 +- .../Security/VoloCaptcha/CaptchaException.cs | 15 -- .../Security/VoloCaptcha/CaptchaOptions.cs | 67 ------- .../Security/VoloCaptcha/CaptchaOutput.cs | 32 ---- .../Volo/Security/VoloCaptcha/EncoderTypes.cs | 7 - .../VoloCaptcha/RandomTextGenerator.cs | 73 -------- .../SimpleMathsCaptchaGenerator.cs | 175 ------------------ 7 files changed, 1 insertion(+), 386 deletions(-) delete mode 100644 modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaException.cs delete mode 100644 modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaOptions.cs delete mode 100644 modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaOutput.cs delete mode 100644 modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/EncoderTypes.cs delete mode 100644 modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/RandomTextGenerator.cs delete mode 100644 modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/SimpleMathsCaptchaGenerator.cs diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Comments/CommentPublicAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Comments/CommentPublicAppService.cs index 03665d19f9..e36cff5717 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Comments/CommentPublicAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Comments/CommentPublicAppService.cs @@ -3,9 +3,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; -using Microsoft.Extensions.Options; -using SixLabors.ImageSharp.Formats.Gif; -using Volo.Abp; using Volo.Abp.Application.Dtos; using Volo.Abp.Authorization; using Volo.Abp.Data; @@ -16,7 +13,6 @@ using Volo.Abp.Users; using Volo.CmsKit.Comments; using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; -using Volo.CmsKit.Public.Application.Security.VoloCaptcha; using Volo.CmsKit.Users; namespace Volo.CmsKit.Public.Comments; @@ -29,23 +25,17 @@ public class CommentPublicAppService : CmsKitPublicAppServiceBase, ICommentPubli protected ICmsUserLookupService CmsUserLookupService { get; } public IDistributedEventBus DistributedEventBus { get; } protected CommentManager CommentManager { get; } - protected CmsKitCommentOptions CmsKitCommentOptions { get; } - public SimpleMathsCaptchaGenerator SimpleMathsCaptchaGenerator { get; } public CommentPublicAppService( ICommentRepository commentRepository, ICmsUserLookupService cmsUserLookupService, IDistributedEventBus distributedEventBus, - CommentManager commentManager, - IOptions cmsKitCommentOptions, - SimpleMathsCaptchaGenerator simpleMathsCaptchaGenerator) + CommentManager commentManager) { CommentRepository = commentRepository; CmsUserLookupService = cmsUserLookupService; DistributedEventBus = distributedEventBus; CommentManager = commentManager; - CmsKitCommentOptions = cmsKitCommentOptions.Value; - SimpleMathsCaptchaGenerator = simpleMathsCaptchaGenerator; } public virtual async Task> GetListAsync(string entityType, string entityId) @@ -61,11 +51,6 @@ public class CommentPublicAppService : CmsKitPublicAppServiceBase, ICommentPubli [Authorize] public virtual async Task CreateAsync(string entityType, string entityId, CreateCommentInput input) { - if (CmsKitCommentOptions.IsRecaptchaEnabled && input.CaptchaToken.HasValue) - { - SimpleMathsCaptchaGenerator.Validate(input.CaptchaToken.Value, input.CaptchaAnswer); - } - var user = await CmsUserLookupService.GetByIdAsync(CurrentUser.GetId()); if (input.RepliedCommentId.HasValue) @@ -83,7 +68,6 @@ public class CommentPublicAppService : CmsKitPublicAppServiceBase, ICommentPubli ) ); - await UnitOfWorkManager.Current.SaveChangesAsync(); await DistributedEventBus.PublishAsync(new CreatedCommentEvent diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaException.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaException.cs deleted file mode 100644 index 4d0362f5ee..0000000000 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaException.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Runtime.Serialization; -using Volo.Abp; - -namespace Volo.CmsKit.Public.Application.Security.VoloCaptcha; - -public class CaptchaException : UserFriendlyException -{ - public CaptchaException(string message) : base(message) - { - } - - public CaptchaException(SerializationInfo serializationInfo, StreamingContext context) : base(serializationInfo, context) - { - } -} \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaOptions.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaOptions.cs deleted file mode 100644 index 33811f25f2..0000000000 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaOptions.cs +++ /dev/null @@ -1,67 +0,0 @@ -using SixLabors.Fonts; -using SixLabors.ImageSharp; -using SixLabors.ImageSharp.Formats; - -namespace Volo.CmsKit.Public.Application.Security.VoloCaptcha; - -public class CaptchaOptions -{ - /// - /// Default fonts are "Arial", "Verdana", "Times New Roman" in Windows. These fonts must exist in the target OS. - /// - public string[] FontFamilies { get; set; } = new string[] { "Arial", "Verdana", "Times New Roman" }; - - public Color[] TextColor { get; set; } = new Color[] - { - Color.Blue, Color.Black, Color.Black, Color.Brown, Color.Gray, Color.Green - }; - public Color[] DrawLinesColor { get; set; } = new Color[] - { - Color.Blue, Color.Black, Color.Black, Color.Brown, Color.Gray, Color.Green - }; - - public float MinLineThickness { get; set; } = 0.7f; - - public float MaxLineThickness { get; set; } = 2.0f; - - public ushort Width { get; set; } = 180; - - public ushort Height { get; set; } = 70; - - public ushort NoiseRate { get; set; } = 500; - - public Color[] NoiseRateColor { get; set; } = new Color[] { Color.Gray }; - - public byte FontSize { get; set; } = 32; - - public FontStyle FontStyle { get; set; } = FontStyle.Regular; - - public EncoderTypes EncoderType { get; set; } = EncoderTypes.Png; - - public IImageEncoder Encoder => RandomTextGenerator.GetEncoder(EncoderType); - - public byte DrawLines { get; set; } = 2; - - public byte MaxRotationDegrees { get; set; } = 4; - - public int Number1MinValue { get; set; } = 1; - - public int Number1MaxValue { get; set; } = 99; - - public int Number2MinValue { get; set; } = 1; - - public int Number2MaxValue { get; set; } = 99; - - public CaptchaOptions() - { - - } - - public CaptchaOptions(int number1MinValue, int number1MaxValue, int number2MinValue, int number2MaxValue) - { - Number1MinValue = number1MinValue; - Number1MaxValue = number1MaxValue; - Number2MinValue = number2MinValue; - Number1MaxValue = number2MaxValue; - } -} \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaOutput.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaOutput.cs deleted file mode 100644 index 10ddd2e78a..0000000000 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/CaptchaOutput.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; - -namespace Volo.CmsKit.Public.Application.Security.VoloCaptcha; - -public class CaptchaOutput -{ - public Guid Id { get; set; } - public string Text { get; set; } - public byte[] ImageBytes { get; set; } - public int Result { get; set; } -} - -public class CaptchaInput -{ - public int Number1 { get; set; } - public int Number2 { get; set; } -} - -public class CaptchaRequest -{ - public CaptchaInput Input { get; set; } - public CaptchaOutput Output { get; set; } - - public CaptchaRequest() - { - Input = new CaptchaInput(); - Output = new CaptchaOutput - { - Id = Guid.NewGuid() - }; - } -} \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/EncoderTypes.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/EncoderTypes.cs deleted file mode 100644 index 8016903ba4..0000000000 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/EncoderTypes.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Volo.CmsKit.Public.Application.Security.VoloCaptcha; - -public enum EncoderTypes -{ - Jpeg, - Png, -} \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/RandomTextGenerator.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/RandomTextGenerator.cs deleted file mode 100644 index cf7d61bda8..0000000000 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/RandomTextGenerator.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System; -using System.Security.Cryptography; -using System.Text; -using SixLabors.ImageSharp.Formats; -using SixLabors.ImageSharp.Formats.Jpeg; -using SixLabors.ImageSharp.Formats.Png; - -namespace Volo.CmsKit.Public.Application.Security.VoloCaptcha; -public static class RandomTextGenerator -{ - private static readonly char[] AllowedChars = "abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVXYZW23456789".ToCharArray(); - - public static IImageEncoder GetEncoder(EncoderTypes encoderType) - { - IImageEncoder encoder = encoderType switch - { - EncoderTypes.Png => new PngEncoder(), - EncoderTypes.Jpeg => new JpegEncoder(), - _ => throw new ArgumentException($"Encoder '{encoderType}' not found!") - }; - - return encoder; - } - - public static string GetRandomText(int size) - { - var data = new byte[4 * size]; - using (var crypto = new RNGCryptoServiceProvider()) - { - crypto.GetBytes(data); - } - - var result = new StringBuilder(size); - for (var i = 0; i < size; i++) - { - var rnd = BitConverter.ToUInt32(data, i * 4); - var idx = rnd % AllowedChars.Length; - result.Append(AllowedChars[idx]); - } - - return result.ToString(); - } - - public static string GetUniqueKey(int size, char[] chars) - { - var data = new byte[4 * size]; - using (var crypto = new RNGCryptoServiceProvider()) - { - crypto.GetBytes(data); - } - - var result = new StringBuilder(size); - - for (var i = 0; i < size; i++) - { - var rnd = BitConverter.ToUInt32(data, i * 4); - var idx = rnd % chars.Length; - result.Append(chars[idx]); - } - - return result.ToString(); - } - - public static float GenerateNextFloat(double min = -3.40282347E+38, double max = 3.40282347E+38) - { - var random = new Random(); - var range = max - min; - var sample = random.NextDouble(); - var scaled = sample * range + min; - var result = (float)scaled; - return result; - } -} diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/SimpleMathsCaptchaGenerator.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/SimpleMathsCaptchaGenerator.cs deleted file mode 100644 index 595426658a..0000000000 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/Security/VoloCaptcha/SimpleMathsCaptchaGenerator.cs +++ /dev/null @@ -1,175 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Numerics; -using System.Threading.Tasks; -using SixLabors.Fonts; -using SixLabors.ImageSharp; -using SixLabors.ImageSharp.Drawing.Processing; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using Volo.Abp.DependencyInjection; -using Color = SixLabors.ImageSharp.Color; -using PointF = SixLabors.ImageSharp.PointF; - -namespace Volo.CmsKit.Public.Application.Security.VoloCaptcha; - -public class SimpleMathsCaptchaGenerator : ISingletonDependency -{ - private static Dictionary Session { get; set; } = new Dictionary(); - - public CaptchaOutput Generate() - { - return Generate(options: null, number1: null, number2: null); - } - - public CaptchaOutput Generate(CaptchaOptions options) - { - return Generate(options, number1: null, number2: null); - } - - /// - /// Creates a simple captcha code. - /// - /// Options for captcha generation - /// First number for maths operation - /// Second number for maths operation - /// - public CaptchaOutput Generate(CaptchaOptions options, int? number1, int? number2) - { - var random = new Random(); - options ??= new CaptchaOptions(); - - number1 ??= random.Next(options.Number1MinValue, options.Number1MaxValue); - number2 ??= random.Next(options.Number2MinValue, options.Number2MaxValue); - - var text = number1 + "+" + number2; - var request = new CaptchaRequest - { - Input = - { - Number1 = number1.Value, - Number2 = number2.Value - }, - Output = - { - Text = text, - Result = Calculate(number1.Value, number2.Value), - ImageBytes = GenerateInternal(text, options) - } - }; - - Session[request.Output.Id] = request; - return request.Output; - } - - private static int Calculate(int number1, int number2) - { - return number1 + number2; - } - - public void Validate(Guid requestId, int value) - { - var request = Session[requestId]; - if (request.Output.Result != value) - { - throw new CaptchaException("The captcha code doesn't match text on the picture! Please try again."); - } - } - - public void Validate(Guid requestId, string value) - { - if (int.TryParse(value, out var captchaInput)) - { - Validate(requestId, captchaInput); - } - else - { - throw new CaptchaException("The captcha code is missing!"); - } - } - - private byte[] GenerateInternal(string stringText, CaptchaOptions options) - { - byte[] result; - - using (var image = new Image(options.Width, options.Height)) - { - float position = 0; - var random = new Random(); - var startWith = (byte)random.Next(5, 10); - image.Mutate(ctx => ctx.BackgroundColor(Color.Transparent)); - var fontName = options.FontFamilies[random.Next(0, options.FontFamilies.Length)]; - var font = SystemFonts.CreateFont(fontName, options.FontSize, options.FontStyle); - - foreach (var character in stringText) - { - var text = character.ToString(); - var color = options.TextColor[random.Next(0, options.TextColor.Length)]; - var location = new PointF(startWith + position, random.Next(6, 13)); - image.Mutate(ctx => ctx.DrawText(text, font, color, location)); - position += TextMeasurer.Measure(character.ToString(), new RendererOptions(font, location)).Width; - } - - //add rotation - var rotation = GetRotation(options); - image.Mutate(ctx => ctx.Transform(rotation)); - - // add the dynamic image to original image - var size = (ushort)TextMeasurer.Measure(stringText, new RendererOptions(font)).Width; - var img = new Image(size + 15, options.Height); - img.Mutate(ctx => ctx.BackgroundColor(Color.White)); - - Parallel.For(0, options.DrawLines, i => - { - var x0 = random.Next(0, random.Next(0, 30)); - var y0 = random.Next(10, img.Height); - - var x1 = random.Next(30, img.Width); - var y1 = random.Next(0, img.Height); - - img.Mutate(ctx => - ctx.DrawLines(options.TextColor[random.Next(0, options.TextColor.Length)], - RandomTextGenerator.GenerateNextFloat(options.MinLineThickness, options.MaxLineThickness), - new PointF[] { new PointF(x0, y0), new PointF(x1, y1) }) - ); - }); - - img.Mutate(ctx => ctx.DrawImage(image, 0.80f)); - - Parallel.For(0, options.NoiseRate, i => - { - var x0 = random.Next(0, img.Width); - var y0 = random.Next(0, img.Height); - img.Mutate( - ctx => ctx - .DrawLines(options.NoiseRateColor[random.Next(0, options.NoiseRateColor.Length)], - RandomTextGenerator.GenerateNextFloat(0.5, 1.5), new PointF[] { new Vector2(x0, y0), new Vector2(x0, y0) }) - ); - }); - - img.Mutate(x => - { - x.Resize(options.Width, options.Height); - }); - - using (var ms = new MemoryStream()) - { - img.Save(ms, options.Encoder); - result = ms.ToArray(); - } - } - - return result; - } - - private static AffineTransformBuilder GetRotation(CaptchaOptions options) - { - var random = new Random(); - var width = random.Next(10, options.Width); - var height = random.Next(10, options.Height); - var pointF = new PointF(width, height); - var rotationDegrees = random.Next(0, options.MaxRotationDegrees); - return new AffineTransformBuilder().PrependRotationDegrees(rotationDegrees, pointF); - } -} \ No newline at end of file From 13986dd46b5ab279997c5a45bb71d84a1e1a4c56 Mon Sep 17 00:00:00 2001 From: malik masis Date: Fri, 9 Dec 2022 14:49:00 +0300 Subject: [PATCH 16/22] Moved options to remove dependency in web app --- .../Volo/CmsKit/Comments/CmsKitCommentOptions.cs | 0 .../Volo/CmsKit/Comments/CommentEntityTypeDefinition.cs | 1 - .../Volo/CmsKit/EntityTypeDefinition.cs | 0 3 files changed, 1 deletion(-) rename modules/cms-kit/src/{Volo.CmsKit.Domain => Volo.CmsKit.Domain.Shared}/Volo/CmsKit/Comments/CmsKitCommentOptions.cs (100%) rename modules/cms-kit/src/{Volo.CmsKit.Domain => Volo.CmsKit.Domain.Shared}/Volo/CmsKit/Comments/CommentEntityTypeDefinition.cs (95%) rename modules/cms-kit/src/{Volo.CmsKit.Domain => Volo.CmsKit.Domain.Shared}/Volo/CmsKit/EntityTypeDefinition.cs (100%) diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/CmsKitCommentOptions.cs b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Comments/CmsKitCommentOptions.cs similarity index 100% rename from modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/CmsKitCommentOptions.cs rename to modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Comments/CmsKitCommentOptions.cs diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/CommentEntityTypeDefinition.cs b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Comments/CommentEntityTypeDefinition.cs similarity index 95% rename from modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/CommentEntityTypeDefinition.cs rename to modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Comments/CommentEntityTypeDefinition.cs index 3dfa822f6a..1cbfc2e215 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/CommentEntityTypeDefinition.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Comments/CommentEntityTypeDefinition.cs @@ -1,5 +1,4 @@ using JetBrains.Annotations; -using System; using Volo.Abp; namespace Volo.CmsKit.Comments; diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/EntityTypeDefinition.cs b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/EntityTypeDefinition.cs similarity index 100% rename from modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/EntityTypeDefinition.cs rename to modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/EntityTypeDefinition.cs From 61f0a0f17de14c21bde20cdd2f28408f14b8ae39 Mon Sep 17 00:00:00 2001 From: malik masis Date: Fri, 9 Dec 2022 14:49:48 +0300 Subject: [PATCH 17/22] Added a new controller to web for removing the app layer --- .../CreateCommentWithParameteresInput.cs | 26 ++++++++++ .../CmsKitPublicCommentsController.cs | 47 +++++++++++++++++++ .../Commenting/CommentingViewComponent.cs | 5 +- .../Shared/Components/Commenting/default.js | 20 +++++--- 4 files changed, 88 insertions(+), 10 deletions(-) create mode 100644 modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Comments/CreateCommentWithParameteresInput.cs create mode 100644 modules/cms-kit/src/Volo.CmsKit.Public.Web/Controllers/CmsKitPublicCommentsController.cs diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Comments/CreateCommentWithParameteresInput.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Comments/CreateCommentWithParameteresInput.cs new file mode 100644 index 0000000000..7e156ef375 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Comments/CreateCommentWithParameteresInput.cs @@ -0,0 +1,26 @@ +using System; +using System.ComponentModel.DataAnnotations; +using Volo.Abp.Validation; +using Volo.CmsKit.Comments; + +namespace Volo.CmsKit.Public.Comments; + +[Serializable] +public class CreateCommentWithParameteresInput +{ + [Required] + [DynamicStringLength(typeof(CommentConsts), nameof(CommentConsts.MaxTextLength))] + public string Text { get; set; } + + [Required] + public string EntityType { get; set; } + + [Required] + public string EntityId { get; set; } + + public Guid? RepliedCommentId { get; set; } + + public Guid? CaptchaToken { get; set; } + + public int CaptchaAnswer { get; set; } +} diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Controllers/CmsKitPublicCommentsController.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Controllers/CmsKitPublicCommentsController.cs new file mode 100644 index 0000000000..89dea5001f --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Controllers/CmsKitPublicCommentsController.cs @@ -0,0 +1,47 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; +using Volo.Abp.AspNetCore.Mvc; +using Volo.CmsKit.Comments; +using Volo.CmsKit.Public.Comments; +using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Commenting; +using Volo.CmsKit.Public.Web.Security.Captcha; + +namespace Volo.CmsKit.Public.Web.Controllers; + +//[Route("cms-kit/public-comments")] +public class CmsKitPublicCommentsController : AbpController +{ + public ICommentPublicAppService CommentPublicAppService { get; } + protected CmsKitCommentOptions CmsKitCommentOptions { get; } + public SimpleMathsCaptchaGenerator SimpleMathsCaptchaGenerator { get; } + + public CmsKitPublicCommentsController( + ICommentPublicAppService commentPublicAppService, + IOptions cmsKitCommentOptions, + SimpleMathsCaptchaGenerator simpleMathsCaptchaGenerator) + { + CommentPublicAppService = commentPublicAppService; + CmsKitCommentOptions = cmsKitCommentOptions.Value; + SimpleMathsCaptchaGenerator = simpleMathsCaptchaGenerator; + } + + [HttpPost] + public async Task ValidateAsync([FromBody] CreateCommentWithParameteresInput input) + { + if (CmsKitCommentOptions.IsRecaptchaEnabled && input.CaptchaToken.HasValue) + { + SimpleMathsCaptchaGenerator.Validate(input.CaptchaToken.Value, input.CaptchaAnswer); + } + + await CommentPublicAppService.CreateAsync(input.EntityType, input.EntityId, + new CreateCommentInput() + { + Text = input.Text, + RepliedCommentId = input.RepliedCommentId, + CaptchaAnswer = input.CaptchaAnswer, + CaptchaToken = input.CaptchaToken + }); + } +} diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/CommentingViewComponent.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/CommentingViewComponent.cs index 6e1db54a5b..bdf8d3ffa0 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/CommentingViewComponent.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/CommentingViewComponent.cs @@ -9,8 +9,8 @@ using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc.UI; using Volo.Abp.AspNetCore.Mvc.UI.Widgets; using Volo.CmsKit.Comments; -using Volo.CmsKit.Public.Application.Security.VoloCaptcha; using Volo.CmsKit.Public.Comments; +using Volo.CmsKit.Public.Web.Security.Captcha; using Volo.CmsKit.Web.Renderers; namespace Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Commenting; @@ -129,9 +129,6 @@ public class CommentingViewComponent : AbpViewComponent public string Captcha { get; set; } public string CaptchaImageBase64 { get; set; } - - - } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js index 7c4b86712e..0e8e99c2bc 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js @@ -127,17 +127,25 @@ formAsObject.repliedCommentId = null; } - volo.cmsKit.public.comments.commentPublic.create( - $commentArea.attr('data-entity-type'), - $commentArea.attr('data-entity-id'), - { + $.ajax({ + type: 'POST', + url: 'CmsKitPublicComments/Validate', + contentType: 'application/json; charset=utf-8', + dataType: 'json', + data: JSON.stringify({ + entityId: $commentArea.attr('data-entity-id'), + entityType: $commentArea.attr('data-entity-type'), repliedCommentId: formAsObject.repliedCommentId, text: formAsObject.commentText, captchaToken: formAsObject.captchaId, captchaAnswer: formAsObject.input?.captcha + }), + success: function () { + widgetManager.refresh($widget); + }, + error: function (data) { + abp.message.error(data.responseJSON.error.message); } - ).then(function () { - widgetManager.refresh($widget); }); }); }); From 9884a7aa19914da0a3fb4e4674f8b85301001f3c Mon Sep 17 00:00:00 2001 From: malik masis Date: Fri, 9 Dec 2022 15:02:08 +0300 Subject: [PATCH 18/22] Used AutoMapper instead of mapping one by one --- .../CmsKit/Admin/Comments/CommentWithAuthorDto.cs | 2 -- .../CmsKitPublicWebAutoMapperProfile.cs | 4 +++- .../Controllers/CmsKitPublicCommentsController.cs | 11 +++-------- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentWithAuthorDto.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentWithAuthorDto.cs index 18eaa9a4c6..ab833cfb3b 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentWithAuthorDto.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentWithAuthorDto.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using Volo.CmsKit.Users; namespace Volo.CmsKit.Admin.Comments; diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/CmsKitPublicWebAutoMapperProfile.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/CmsKitPublicWebAutoMapperProfile.cs index f5884149d4..3c44f6fa1c 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/CmsKitPublicWebAutoMapperProfile.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/CmsKitPublicWebAutoMapperProfile.cs @@ -1,4 +1,6 @@ using AutoMapper; +using Volo.CmsKit.Menus; +using Volo.CmsKit.Public.Comments; namespace Volo.CmsKit.Public.Web; @@ -6,6 +8,6 @@ public class CmsKitPublicWebAutoMapperProfile : Profile { public CmsKitPublicWebAutoMapperProfile() { - + CreateMap(); } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Controllers/CmsKitPublicCommentsController.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Controllers/CmsKitPublicCommentsController.cs index 89dea5001f..bb2487587b 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Controllers/CmsKitPublicCommentsController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Controllers/CmsKitPublicCommentsController.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.ObjectMapping; using Volo.CmsKit.Comments; using Volo.CmsKit.Public.Comments; using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Commenting; @@ -35,13 +36,7 @@ public class CmsKitPublicCommentsController : AbpController SimpleMathsCaptchaGenerator.Validate(input.CaptchaToken.Value, input.CaptchaAnswer); } - await CommentPublicAppService.CreateAsync(input.EntityType, input.EntityId, - new CreateCommentInput() - { - Text = input.Text, - RepliedCommentId = input.RepliedCommentId, - CaptchaAnswer = input.CaptchaAnswer, - CaptchaToken = input.CaptchaToken - }); + var dto = ObjectMapper.Map (input); + await CommentPublicAppService.CreateAsync(input.EntityType, input.EntityId, dto); } } From 9eec50defecec3f0c27abff8955f880008bedbb8 Mon Sep 17 00:00:00 2001 From: malik masis Date: Fri, 9 Dec 2022 15:16:07 +0300 Subject: [PATCH 19/22] Added the missed language words --- .../Volo/CmsKit/Localization/Resources/en.json | 3 ++- .../Volo/CmsKit/Localization/Resources/tr.json | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) 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 a5fa44e2be..3dd90d2ea5 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 @@ -210,6 +210,7 @@ "Feature:ReactionEnableDescription": "CMS Kit's reaction system that allows users to send reactions to entities such as BlogPost, Comments, etc.", "Feature:TagEnable": "Taging", "Feature:TagEnableDescription": "CMS Kit's tag system that allows tagging entities such as BlogPost.", - "DeleteBlogPostMessage": "The blog will be deleted. Are you sure?" + "DeleteBlogPostMessage": "The blog will be deleted. Are you sure?", + "CaptchaCode": "Captcha code" } } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json index a7e2e4702f..76a357cfb6 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json @@ -210,6 +210,7 @@ "Feature:ReactionEnableDescription": "Cmskit reaksiyon sistemi", "Feature:TagEnable": "Etkiket", "Feature:TagEnableDescription": "Cmskit etiket sistemi", - "DeleteBlogPostMessage": "Blog silinecek. Emin misiniz?" + "DeleteBlogPostMessage": "Blog silinecek. Emin misiniz?", + "CaptchaCode": "Captcha kodu" } } From 99908ff8eba01b2f1cf306f9fe2fb83eec346642 Mon Sep 17 00:00:00 2001 From: malik masis Date: Mon, 12 Dec 2022 14:37:36 +0300 Subject: [PATCH 20/22] Update default.js --- .../Pages/CmsKit/Shared/Components/Commenting/default.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js index 0e8e99c2bc..a08039235d 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js @@ -129,7 +129,7 @@ $.ajax({ type: 'POST', - url: 'CmsKitPublicComments/Validate', + url: '/CmsKitPublicComments/Validate', contentType: 'application/json; charset=utf-8', dataType: 'json', data: JSON.stringify({ From 755358858b40782c12062d61cf232d9e37695c1c Mon Sep 17 00:00:00 2001 From: malik masis Date: Mon, 12 Dec 2022 16:45:25 +0300 Subject: [PATCH 21/22] Made requires the comment --- .../Volo/CmsKit/Localization/Resources/en.json | 3 ++- .../Volo/CmsKit/Localization/Resources/tr.json | 3 ++- .../Pages/CmsKit/Shared/Components/Commenting/default.js | 5 +++++ 3 files changed, 9 insertions(+), 2 deletions(-) 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 3dd90d2ea5..cab77cdd26 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 @@ -211,6 +211,7 @@ "Feature:TagEnable": "Taging", "Feature:TagEnableDescription": "CMS Kit's tag system that allows tagging entities such as BlogPost.", "DeleteBlogPostMessage": "The blog will be deleted. Are you sure?", - "CaptchaCode": "Captcha code" + "CaptchaCode": "Captcha code", + "CommentTextRequired": "Comment is required" } } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json index 76a357cfb6..8b817b5985 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json @@ -211,6 +211,7 @@ "Feature:TagEnable": "Etkiket", "Feature:TagEnableDescription": "Cmskit etiket sistemi", "DeleteBlogPostMessage": "Blog silinecek. Emin misiniz?", - "CaptchaCode": "Captcha kodu" + "CaptchaCode": "Captcha kodu", + "CommentTextRequired": "Yorum zorunlu" } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js index a08039235d..e0fcca9ad1 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/default.js @@ -127,6 +127,11 @@ formAsObject.repliedCommentId = null; } + if (formAsObject.commentText == '') { + abp.message.error(l("CommentTextRequired")); + return; + } + $.ajax({ type: 'POST', url: '/CmsKitPublicComments/Validate', From 960396ac2eb6fabd44a4312ae0dad71d5c556a38 Mon Sep 17 00:00:00 2001 From: malik masis Date: Mon, 12 Dec 2022 16:45:51 +0300 Subject: [PATCH 22/22] Moved the markdown the right of the component --- .../CmsKit/Shared/Components/Commenting/Default.cshtml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml index 9324eeb40b..ecfbc1cb54 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml @@ -38,6 +38,9 @@
+
+ @L["MarkdownSupported"] +
@if (CmsKitCommentOptions.Value.IsRecaptchaEnabled) { @@ -68,9 +71,6 @@ }
-
- @L["MarkdownSupported"] -
;