From 484d9a2db59f7e359e9c2b2ec7d24f74da3fc831 Mon Sep 17 00:00:00 2001 From: surtur Date: Sun, 24 Jan 2021 19:31:56 +0100 Subject: [PATCH 1/6] chore: add image validation --- Models/Carousel.cs | 2 ++ Models/Validation/FileTypeAttr.cs | 47 +++++++++++++++++++++++++++++++ pwt-0x01-ng.csproj | 1 + 3 files changed, 50 insertions(+) create mode 100644 Models/Validation/FileTypeAttr.cs diff --git a/Models/Carousel.cs b/Models/Carousel.cs index b7c971c..9c7b513 100644 --- a/Models/Carousel.cs +++ b/Models/Carousel.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Http; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using pwt_0x01_ng.Models.Validation; namespace pwt_0x01_ng.Models { @@ -10,6 +11,7 @@ namespace pwt_0x01_ng.Models [Required] public string DataTarget { get; set; } [NotMapped] + [FileTypeAttr("image")] public IFormFile Image { get; set; } [Required] [StringLength(255)] diff --git a/Models/Validation/FileTypeAttr.cs b/Models/Validation/FileTypeAttr.cs new file mode 100644 index 0000000..7a0ecfd --- /dev/null +++ b/Models/Validation/FileTypeAttr.cs @@ -0,0 +1,47 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using Microsoft.AspNetCore.Http; + +namespace pwt_0x01_ng.Models.Validation +{ + public class FileTypeAttr : ValidationAttribute, IClientModelValidator + { + private readonly string type; + public FileTypeAttr(string type){ + this.type = type.ToLower(); + } + + protected override ValidationResult IsValid(object value, ValidationContext validationContext) { + if (value == null) { + /* img is optional as of now */ + return ValidationResult.Success; + } else if (value is IFormFile iff) { + if(iff.ContentType.ToLower().Contains(type)) { + return ValidationResult.Success; + } else { + return new ValidationResult(GetErrorMessage(validationContext.MemberName), new List { validationContext.MemberName }); + } + } + throw new NotImplementedException($"Attribute {nameof(FileTypeAttr)} not implemented for object {value.GetType()}."); + } + + protected string GetErrorMessage(string member_name) => $"make sure your {member_name} really is an image ({type})."; + + public void AddValidation(ClientModelValidationContext ctx){ + MergeAttribute(ctx.Attributes, "data-val", "true"); + MergeAttribute(ctx.Attributes, "data-val-content", GetErrorMessage("File")); + MergeAttribute(ctx.Attributes, "data-val-filetype", type); + } + + private bool MergeAttribute(IDictionary attributes, string key, string value){ + if (attributes.ContainsKey(key)){ + return false; + } + + Attributes.Add(key, value); + return true; + } + } +} \ No newline at end of file diff --git a/pwt-0x01-ng.csproj b/pwt-0x01-ng.csproj index 439d273..70b5bcd 100644 --- a/pwt-0x01-ng.csproj +++ b/pwt-0x01-ng.csproj @@ -28,6 +28,7 @@ + -- 2.48.1 From b19c4a7c00744d5cc3f4b5fcf69629198322805a Mon Sep 17 00:00:00 2001 From: surtur Date: Mon, 25 Jan 2021 16:30:37 +0100 Subject: [PATCH 2/6] fix: typo and missing using --- Models/Validation/FileTypeAttr.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Models/Validation/FileTypeAttr.cs b/Models/Validation/FileTypeAttr.cs index 7a0ecfd..4c6feb0 100644 --- a/Models/Validation/FileTypeAttr.cs +++ b/Models/Validation/FileTypeAttr.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; namespace pwt_0x01_ng.Models.Validation { @@ -40,7 +41,7 @@ namespace pwt_0x01_ng.Models.Validation return false; } - Attributes.Add(key, value); + attributes.Add(key, value); return true; } } -- 2.48.1 From cf223daf81706d2fbfafa47c07da41e2d066f516 Mon Sep 17 00:00:00 2001 From: surtur Date: Mon, 25 Jan 2021 22:32:34 +0100 Subject: [PATCH 3/6] chore: more carousel validation goodies commit 81a5fe36c2aef355aa71a6208acea096dd35d70e Author: surtur Date: Mon Jan 25 22:29:48 2021 +0100 chore: add client-side carousel edit validation commit 5cddb4bd9b55a514d9aa6f79f291678c88d33773 Author: surtur Date: Mon Jan 25 22:27:38 2021 +0100 chore: add carousel image file type checking * since image is not required, so isn't ImageSrc --- Areas/Admin/Views/Carousel/Create.cshtml | 1 + Areas/Admin/Views/Carousel/Edit.cshtml | 1 + .../Carousel/PartialForm_EditCreate.cshtml | 2 +- Models/Carousel.cs | 1 - Models/Validation/FileTypeAttr.cs | 6 ++--- wwwroot/js/validation/file_type.js | 25 +++++++++++++++++++ 6 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 wwwroot/js/validation/file_type.js diff --git a/Areas/Admin/Views/Carousel/Create.cshtml b/Areas/Admin/Views/Carousel/Create.cshtml index c3b04e5..500cd02 100644 --- a/Areas/Admin/Views/Carousel/Create.cshtml +++ b/Areas/Admin/Views/Carousel/Create.cshtml @@ -13,4 +13,5 @@ @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} + } diff --git a/Areas/Admin/Views/Carousel/Edit.cshtml b/Areas/Admin/Views/Carousel/Edit.cshtml index 6165230..67999e3 100644 --- a/Areas/Admin/Views/Carousel/Edit.cshtml +++ b/Areas/Admin/Views/Carousel/Edit.cshtml @@ -13,4 +13,5 @@ @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} + } diff --git a/Areas/Admin/Views/Carousel/PartialForm_EditCreate.cshtml b/Areas/Admin/Views/Carousel/PartialForm_EditCreate.cshtml index 6e0e81f..243be2b 100644 --- a/Areas/Admin/Views/Carousel/PartialForm_EditCreate.cshtml +++ b/Areas/Admin/Views/Carousel/PartialForm_EditCreate.cshtml @@ -17,7 +17,7 @@
- +
diff --git a/Models/Carousel.cs b/Models/Carousel.cs index 9c7b513..05a820d 100644 --- a/Models/Carousel.cs +++ b/Models/Carousel.cs @@ -13,7 +13,6 @@ namespace pwt_0x01_ng.Models [NotMapped] [FileTypeAttr("image")] public IFormFile Image { get; set; } - [Required] [StringLength(255)] public string ImageSrc { get; set; } [Required] diff --git a/Models/Validation/FileTypeAttr.cs b/Models/Validation/FileTypeAttr.cs index 4c6feb0..2136bd1 100644 --- a/Models/Validation/FileTypeAttr.cs +++ b/Models/Validation/FileTypeAttr.cs @@ -28,12 +28,12 @@ namespace pwt_0x01_ng.Models.Validation throw new NotImplementedException($"Attribute {nameof(FileTypeAttr)} not implemented for object {value.GetType()}."); } - protected string GetErrorMessage(string member_name) => $"make sure your {member_name} really is an image ({type})."; + protected string GetErrorMessage(string member_name) => $"make sure the {member_name} you picked really is an image ({type}/*)."; public void AddValidation(ClientModelValidationContext ctx){ MergeAttribute(ctx.Attributes, "data-val", "true"); - MergeAttribute(ctx.Attributes, "data-val-content", GetErrorMessage("File")); - MergeAttribute(ctx.Attributes, "data-val-filetype", type); + MergeAttribute(ctx.Attributes, "data-val-content", GetErrorMessage("file")); + MergeAttribute(ctx.Attributes, "data-val-content-type", type); } private bool MergeAttribute(IDictionary attributes, string key, string value){ diff --git a/wwwroot/js/validation/file_type.js b/wwwroot/js/validation/file_type.js new file mode 100644 index 0000000..45461ee --- /dev/null +++ b/wwwroot/js/validation/file_type.js @@ -0,0 +1,25 @@ +$.validator.addMethod('content', function (value, element, params) { + var f_type = params[1] + uploaded_type = ""; + + if (!value) { + return true; + } + + if (element && element.files && element.files.length > 0) { + uploaded_type = element.files[0].type; + } + + if (f_type && uploaded_type != "" && uploaded_type.toLowerCase().includes(f_type)) { + return true; + } + + return false; +}); + +$.validator.unobtrusive.adapters.add('content', ['type'], function (options) { + var element = $(options.form).find('#file')[0]; + + options.rules['content'] = [element, options.params['type']]; + options.messages['content'] = options.message; +}); \ No newline at end of file -- 2.48.1 From 7644066138d528b8678eeb1358f90999c2d3f07c Mon Sep 17 00:00:00 2001 From: surtur Date: Tue, 26 Jan 2021 14:38:19 +0100 Subject: [PATCH 4/6] chore: add Product validation as per #5 commit d0b491d1dc289dedf242a974b1b42e021272234b Author: surtur Date: Tue Jan 26 14:35:05 2021 +0100 chore: add proper Product validation * image file type checking with custom attr commit 81a5fe36c2aef355aa71a6208acea096dd35d70e Author: surtur Date: Mon Jan 25 22:29:48 2021 +0100 chore: add client-side carousel edit validation commit 5cddb4bd9b55a514d9aa6f79f291678c88d33773 Author: surtur Date: Mon Jan 25 22:27:38 2021 +0100 chore: add carousel image file type checking * since image is not required, so isn't ImageSrc --- Areas/Admin/Controllers/ProductController.cs | 17 +++++++++++------ Areas/Admin/Views/Product/Create.cshtml | 1 + Areas/Admin/Views/Product/Edit.cshtml | 1 + .../Admin/Views/Product/edit-create_part.cshtml | 2 +- Models/Product.cs | 4 ++-- 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/Areas/Admin/Controllers/ProductController.cs b/Areas/Admin/Controllers/ProductController.cs index b091f91..3aab295 100644 --- a/Areas/Admin/Controllers/ProductController.cs +++ b/Areas/Admin/Controllers/ProductController.cs @@ -38,13 +38,18 @@ namespace pwt_0x01_ng.Areas.Admin.Controllers [HttpPost] public async Task Create(Product product) { - product.ImageSrc = string.Empty; - MegaUpload mega_upload = new MegaUpload(hosting_env); - await mega_upload.DoMegaUpload(product); + if (ModelState.IsValid) { + product.ImageSrc = string.Empty; + MegaUpload mega_upload = new MegaUpload(hosting_env); + await mega_upload.DoMegaUpload(product); - dbctx.Product.Add(product); - await dbctx.SaveChangesAsync(); - return RedirectToAction(nameof(Select)); + dbctx.Product.Add(product); + await dbctx.SaveChangesAsync(); + return RedirectToAction(nameof(Select)); + } else { + ViewData["Message"] = "error creating Product"; + return View(product); + } } public IActionResult Edit(int id) diff --git a/Areas/Admin/Views/Product/Create.cshtml b/Areas/Admin/Views/Product/Create.cshtml index 0bef27d..a29fca0 100644 --- a/Areas/Admin/Views/Product/Create.cshtml +++ b/Areas/Admin/Views/Product/Create.cshtml @@ -12,4 +12,5 @@ @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} + } diff --git a/Areas/Admin/Views/Product/Edit.cshtml b/Areas/Admin/Views/Product/Edit.cshtml index a2df7c0..02636d2 100644 --- a/Areas/Admin/Views/Product/Edit.cshtml +++ b/Areas/Admin/Views/Product/Edit.cshtml @@ -12,4 +12,5 @@ @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} + } diff --git a/Areas/Admin/Views/Product/edit-create_part.cshtml b/Areas/Admin/Views/Product/edit-create_part.cshtml index 3560e57..953612a 100644 --- a/Areas/Admin/Views/Product/edit-create_part.cshtml +++ b/Areas/Admin/Views/Product/edit-create_part.cshtml @@ -27,7 +27,7 @@
- +
diff --git a/Models/Product.cs b/Models/Product.cs index 3ee2cd6..ed9aee3 100644 --- a/Models/Product.cs +++ b/Models/Product.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Http; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using pwt_0x01_ng.Models.Validation; namespace pwt_0x01_ng.Models { @@ -13,10 +14,9 @@ namespace pwt_0x01_ng.Models public int Price { get; set; } [Required] public string Description { get; set; } - [Required] + [FileTypeAttr("image")] [NotMapped] public IFormFile Image { get; set; } - [Required] [StringLength(255)] public string ImageSrc { get; set; } [Required] -- 2.48.1 From 9e90f3ee287624381a72c9fda68193a716cd4d59 Mon Sep 17 00:00:00 2001 From: surtur Date: Tue, 26 Jan 2021 14:57:41 +0100 Subject: [PATCH 5/6] chore: reword attr err msg + add help link --- Models/Validation/FileTypeAttr.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Models/Validation/FileTypeAttr.cs b/Models/Validation/FileTypeAttr.cs index 2136bd1..a376d4a 100644 --- a/Models/Validation/FileTypeAttr.cs +++ b/Models/Validation/FileTypeAttr.cs @@ -28,7 +28,7 @@ namespace pwt_0x01_ng.Models.Validation throw new NotImplementedException($"Attribute {nameof(FileTypeAttr)} not implemented for object {value.GetType()}."); } - protected string GetErrorMessage(string member_name) => $"make sure the {member_name} you picked really is an image ({type}/*)."; + protected string GetErrorMessage(string member_name) => $"make sure the {member_name} you picked really is of type {type}/*. help"; public void AddValidation(ClientModelValidationContext ctx){ MergeAttribute(ctx.Attributes, "data-val", "true"); -- 2.48.1 From 6f6ebaa6fabc4b58cb5f5b9dfd8904a754c6d135 Mon Sep 17 00:00:00 2001 From: surtur Date: Tue, 26 Jan 2021 15:08:12 +0100 Subject: [PATCH 6/6] cleanup: rm redundant ids --- Areas/Admin/Views/Carousel/PartialForm_EditCreate.cshtml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Areas/Admin/Views/Carousel/PartialForm_EditCreate.cshtml b/Areas/Admin/Views/Carousel/PartialForm_EditCreate.cshtml index 243be2b..df709c3 100644 --- a/Areas/Admin/Views/Carousel/PartialForm_EditCreate.cshtml +++ b/Areas/Admin/Views/Carousel/PartialForm_EditCreate.cshtml @@ -12,22 +12,22 @@ }}
- +
- +
- +
- +
-- 2.48.1