From 423326fff13c7f920ce2a67567de60f3eb43be63 Mon Sep 17 00:00:00 2001 From: mkoper02 Date: Mon, 6 May 2024 18:11:26 +0200 Subject: [PATCH 01/24] Created basic validators for all models in db --- Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj | 1 - Server/ReasnAPI/ReasnAPI/Validators/.gitkeep | 0 .../ReasnAPI/Validators/AddressValidator.cs | 56 ++++++++++++ .../ReasnAPI/Validators/CommentValidator.cs | 42 +++++++++ .../ReasnAPI/Validators/EventValidator.cs | 81 +++++++++++++++++ .../ReasnAPI/Validators/IValidator.cs | 9 ++ .../ReasnAPI/Validators/ImageValidator.cs | 21 +++++ .../ReasnAPI/Validators/InterestValidator.cs | 21 +++++ .../Validators/ObjectTypeValidator.cs | 21 +++++ .../ReasnAPI/Validators/ParameterValidator.cs | 31 +++++++ .../ReasnAPI/Validators/RoleValidator.cs | 21 +++++ .../ReasnAPI/Validators/StatusValidator.cs | 26 ++++++ .../ReasnAPI/Validators/TagValidator.cs | 21 +++++ .../ReasnAPI/Validators/UserValidator.cs | 86 +++++++++++++++++++ 14 files changed, 436 insertions(+), 1 deletion(-) delete mode 100644 Server/ReasnAPI/ReasnAPI/Validators/.gitkeep create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/IValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs diff --git a/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj b/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj index 23499ae8..02ce3550 100644 --- a/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj +++ b/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj @@ -25,7 +25,6 @@ - diff --git a/Server/ReasnAPI/ReasnAPI/Validators/.gitkeep b/Server/ReasnAPI/ReasnAPI/Validators/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs new file mode 100644 index 00000000..a343a508 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs @@ -0,0 +1,56 @@ +using ReasnAPI.Models.Database; +using System.ComponentModel.DataAnnotations; + +namespace ReasnAPI.Validators +{ + public class AddressValidator : IValidator
+ { + public static IEnumerable Validate(Address address) + { + if (string.IsNullOrWhiteSpace(address.City)) + { + yield return new ValidationResult("City is required", [nameof(address.City)]); + } + + if (address.City.Length > 64) + { + yield return new ValidationResult("City is too long", [nameof(address.City)]); + } + + if (string.IsNullOrWhiteSpace(address.Country)) + { + yield return new ValidationResult("Country is required", [nameof(address.Country)]); + } + + if (address.Country.Length > 64) + { + yield return new ValidationResult("Country is too long", [nameof(address.Country)]); + } + + if (string.IsNullOrWhiteSpace(address.Street)) + { + yield return new ValidationResult("Street is required", [nameof(address.Street)]); + } + + if (address.Street.Length > 64) + { + yield return new ValidationResult("Street is too long", [nameof(address.Street)]); + } + + if (string.IsNullOrWhiteSpace(address.State)) + { + yield return new ValidationResult("State is required", [nameof(address.State)]); + } + + if (address.State.Length > 64) + { + yield return new ValidationResult("State is too long", [nameof(address.State)]); + } + + if (!string.IsNullOrWhiteSpace(address.ZipCode) && address.ZipCode.Length > 8 ) + { + yield return new ValidationResult("ZipCode is too long", [nameof(address.ZipCode)]); + } + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs new file mode 100644 index 00000000..e4fd2264 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs @@ -0,0 +1,42 @@ +using ReasnAPI.Models.Database; +using System.ComponentModel.DataAnnotations; +using System.Numerics; + +namespace ReasnAPI.Validators +{ + public class CommentValidator : IValidator + { + public static IEnumerable Validate(Comment comment) + { + if (string.IsNullOrWhiteSpace(comment.EventId.ToString())) + { + yield return new ValidationResult("EventId is required", [nameof(comment.EventId)]); + } + + if (string.IsNullOrWhiteSpace(comment.Content)) + { + yield return new ValidationResult("Content is required", [nameof(comment.Content)]); + } + + if (comment.Content.Length > 1024) + { + yield return new ValidationResult("Content is too long", [nameof(comment.Content)]); + } + + if (string.IsNullOrWhiteSpace(comment.CreatedAt.ToString())) + { + yield return new ValidationResult("CreatedAt is required", [nameof(comment.CreatedAt)]); + } + + if (comment.CreatedAt > DateTime.Now) + { + yield return new ValidationResult("CreatedAt is in the future", [nameof(comment.CreatedAt)]); + } + + if (string.IsNullOrWhiteSpace(comment.UserId.ToString())) + { + yield return new ValidationResult("UserId is required", [nameof(comment.UserId)]); + } + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs new file mode 100644 index 00000000..5cb71047 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs @@ -0,0 +1,81 @@ +using ReasnAPI.Models.Database; +using System.ComponentModel.DataAnnotations; + +namespace ReasnAPI.Validators +{ + public class EventValidator : IValidator + { + public static IEnumerable Validate(Event eventData) + { + if (string.IsNullOrWhiteSpace(eventData.Name)) + { + yield return new ValidationResult("Name is required", [nameof(eventData.Name)]); + } + + if (eventData.Name.Length > 64) + { + yield return new ValidationResult("Name is too long", [nameof(eventData.Name)]); + } + + if (string.IsNullOrWhiteSpace(eventData.AddressId.ToString())) + { + yield return new ValidationResult("AddressId is required", [nameof(eventData.AddressId)]); + } + + if (string.IsNullOrWhiteSpace(eventData.Description)) + { + yield return new ValidationResult("Description is required", [nameof(eventData.Description)]); + } + + if (eventData.Description.Length > 4048) + { + yield return new ValidationResult("Description is too long", [nameof(eventData.Description)]); + } + + if (string.IsNullOrWhiteSpace(eventData.OrganizerId.ToString())) + { + yield return new ValidationResult("OrganizerId is required", [nameof(eventData.OrganizerId)]); + } + + if (string.IsNullOrWhiteSpace(eventData.StartAt.ToString())) + { + yield return new ValidationResult("StartTime is required", [nameof(eventData.StartAt)]); + } + + if (string.IsNullOrWhiteSpace(eventData.EndAt.ToString())) + { + yield return new ValidationResult("EndTime is required", [nameof(eventData.EndAt)]); + } + + if (eventData.StartAt > eventData.EndAt) + { + yield return new ValidationResult("StartTime is after EndTime", [nameof(eventData.StartAt)]); + } + + if (string.IsNullOrWhiteSpace(eventData.CreatedAt.ToString())) + { + yield return new ValidationResult("CreatedAt is required", [nameof(eventData.CreatedAt)]); + } + + if (string.IsNullOrWhiteSpace(eventData.UpdatedAt.ToString())) + { + yield return new ValidationResult("UpdatedAt is required", [nameof(eventData.UpdatedAt)]); + } + + if (string.IsNullOrWhiteSpace(eventData.Slug)) + { + yield return new ValidationResult("Slug is required", [nameof(eventData.Slug)]); + } + + if (eventData.Slug.Length > 128) + { + yield return new ValidationResult("Slug is too long", [nameof(eventData.Slug)]); + } + + if (string.IsNullOrWhiteSpace(eventData.StatusId.ToString())) + { + yield return new ValidationResult("StatusId is required", [nameof(eventData.StatusId)]); + } + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/IValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/IValidator.cs new file mode 100644 index 00000000..12db5b9b --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/IValidator.cs @@ -0,0 +1,9 @@ +using System.ComponentModel.DataAnnotations; + +namespace ReasnAPI.Validators +{ + public interface IValidator + { + static abstract IEnumerable Validate(T objectToValidate); + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs new file mode 100644 index 00000000..15de2bfc --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs @@ -0,0 +1,21 @@ +using ReasnAPI.Models.Database; +using System.ComponentModel.DataAnnotations; + +namespace ReasnAPI.Validators +{ + public class ImageValidator : IValidator + { + public static IEnumerable Validate(Image image) + { + if (string.IsNullOrWhiteSpace(image.ObjectTypeId.ToString())) + { + yield return new ValidationResult("ObjectTypeId is required", [nameof(image.ObjectTypeId)]); + } + + if (string.IsNullOrWhiteSpace(image.ObjectId.ToString())) + { + yield return new ValidationResult("ObjectId is required", [nameof(image.ObjectId)]); + } + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs new file mode 100644 index 00000000..4729cb1e --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs @@ -0,0 +1,21 @@ +using ReasnAPI.Models.Database; +using System.ComponentModel.DataAnnotations; + +namespace ReasnAPI.Validators +{ + public class InterestValidator : IValidator + { + public static IEnumerable Validate(Interest interest) + { + if (string.IsNullOrWhiteSpace(interest.Name)) + { + yield return new ValidationResult("Name is required", [nameof(interest.Name)]); + } + + if (interest.Name.Length > 32) + { + yield return new ValidationResult("Name is too long", [nameof(interest.Name)]); + } + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs new file mode 100644 index 00000000..db634df6 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs @@ -0,0 +1,21 @@ +using ReasnAPI.Models.Database; +using System.ComponentModel.DataAnnotations; + +namespace ReasnAPI.Validators +{ + public class ObjectTypeValidator : IValidator + { + public static IEnumerable Validate(ObjectType objectType) + { + if (string.IsNullOrWhiteSpace(objectType.Name)) + { + yield return new ValidationResult("Name is required", [nameof(objectType.Name)]); + } + + if (objectType.Name.Length > 32) + { + yield return new ValidationResult("Name is too long", [nameof(objectType.Name)]); + } + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs new file mode 100644 index 00000000..b5271925 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs @@ -0,0 +1,31 @@ +using ReasnAPI.Models.Database; +using System.ComponentModel.DataAnnotations; + +namespace ReasnAPI.Validators +{ + public class ParameterValidator : IValidator + { + public static IEnumerable Validate(Parameter parameter) + { + if (string.IsNullOrWhiteSpace(parameter.Key)) + { + yield return new ValidationResult("Key is required", [nameof(parameter.Key)]); + } + + if (parameter.Key.Length > 32) + { + yield return new ValidationResult("Key is too long", [nameof(parameter.Key)]); + } + + if (string.IsNullOrWhiteSpace(parameter.Value)) + { + yield return new ValidationResult("Value is required", [nameof(parameter.Value)]); + } + + if (parameter.Value.Length > 64) + { + yield return new ValidationResult("Value is too long", [nameof(parameter.Value)]); + } + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs new file mode 100644 index 00000000..119b2f9d --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs @@ -0,0 +1,21 @@ +using ReasnAPI.Models.Database; +using System.ComponentModel.DataAnnotations; + +namespace ReasnAPI.Validators +{ + public class RoleValidator : IValidator + { + public static IEnumerable Validate(Role role) + { + if (string.IsNullOrWhiteSpace(role.Name)) + { + yield return new ValidationResult("Role name is required", [nameof(role.Name)]); + } + + if (role.Name.Length > 32) + { + yield return new ValidationResult("Role name is too long", [nameof(role.Name)]); + } + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs new file mode 100644 index 00000000..579f0faa --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs @@ -0,0 +1,26 @@ +using ReasnAPI.Models.Database; +using System.ComponentModel.DataAnnotations; + +namespace ReasnAPI.Validators +{ + public class StatusValidator : IValidator + { + public static IEnumerable Validate(Status status) + { + if (string.IsNullOrWhiteSpace(status.Name)) + { + yield return new ValidationResult("Name is required", [nameof(status.Name)]); + } + + if (status.Name.Length > 32) + { + yield return new ValidationResult("Name is too long", [nameof(status.Name)]); + } + + if (string.IsNullOrWhiteSpace(status.ObjectTypeId.ToString())) + { + yield return new ValidationResult("ObjectTypeId is required", [nameof(status.ObjectTypeId)]); + } + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs new file mode 100644 index 00000000..ecae1929 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs @@ -0,0 +1,21 @@ +using ReasnAPI.Models.Database; +using System.ComponentModel.DataAnnotations; + +namespace ReasnAPI.Validators +{ + public class TagValidator : IValidator + { + public static IEnumerable Validate(Tag tag) + { + if (string.IsNullOrWhiteSpace(tag.Name)) + { + yield return new ValidationResult("Name is required", [nameof(tag.Name)]); + } + + if (tag.Name.Length > 64) + { + yield return new ValidationResult("Name is too long", [nameof(tag.Name)]); + } + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs new file mode 100644 index 00000000..56da2983 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs @@ -0,0 +1,86 @@ +using ReasnAPI.Models.Database; +using System.ComponentModel.DataAnnotations; + +namespace ReasnAPI.Validators +{ + public class UserValidator : IValidator + { + public static IEnumerable Validate(User user) + { + if (string.IsNullOrWhiteSpace(user.Name)) + { + yield return new ValidationResult("Name is required", [nameof(user.Name)]); + } + + if (user.Name.Length > 64) + { + yield return new ValidationResult("Name is too long", [nameof(user.Name)]); + } + + if (string.IsNullOrWhiteSpace(user.Surname)) + { + yield return new ValidationResult("Surname is required", [nameof(user.Surname)]); + } + + if (user.Surname.Length > 64) + { + yield return new ValidationResult("Surname is too long", [nameof(user.Surname)]); + } + + if (string.IsNullOrWhiteSpace(user.Username)) + { + yield return new ValidationResult("Username is required", [nameof(user.Username)]); + } + + if (user.Username.Length > 64) + { + yield return new ValidationResult("Username is too long", [nameof(user.Username)]); + } + + if (string.IsNullOrWhiteSpace(user.Password)) + { + yield return new ValidationResult("Password is required", [nameof(user.Password)]); + } + + if (string.IsNullOrWhiteSpace(user.CreatedAt.ToString())) + { + yield return new ValidationResult("CreatedAt is required", [nameof(user.CreatedAt)]); + } + + if (string.IsNullOrWhiteSpace(user.UpdatedAt.ToString())) + { + yield return new ValidationResult("UpdatedAt is required", [nameof(user.UpdatedAt)]); + } + + if (string.IsNullOrWhiteSpace(user.RoleId.ToString())) + { + yield return new ValidationResult("RoleId is required", [nameof(user.RoleId)]); + } + + if (string.IsNullOrWhiteSpace(user.Email)) + { + yield return new ValidationResult("Email is required", [nameof(user.Email)]); + } + + if (user.Email.Length > 255) + { + yield return new ValidationResult("Email is too long", [nameof(user.Email)]); + } + + if (string.IsNullOrWhiteSpace(user.AddressId.ToString())) + { + yield return new ValidationResult("AddressId is required", [nameof(user.AddressId)]); + } + + if (string.IsNullOrWhiteSpace(user.Phone)) + { + yield return new ValidationResult("Phone is required", [nameof(user.Phone)]); + } + + if (!string.IsNullOrWhiteSpace(user.Phone) && user.Phone.Length > 16) + { + yield return new ValidationResult("Phone is too long", [nameof(user.Phone)]); + } + } + } +} From 4f39e3862420092f5c91db7e1863bf0aaaee906a Mon Sep 17 00:00:00 2001 From: mkoper02 Date: Sat, 11 May 2024 18:48:50 +0200 Subject: [PATCH 02/24] Created regex check for all models --- .../ReasnAPI/Validators/AddressValidator.cs | 33 ++++++++++++++++- .../ReasnAPI/Validators/EventValidator.cs | 6 +++ .../ReasnAPI/Validators/InterestValidator.cs | 6 +++ .../Validators/ObjectTypeValidator.cs | 6 +++ .../ReasnAPI/Validators/ParameterValidator.cs | 11 ++++++ .../ReasnAPI/Validators/RoleValidator.cs | 6 +++ .../ReasnAPI/Validators/StatusValidator.cs | 6 +++ .../ReasnAPI/Validators/TagValidator.cs | 6 +++ .../ReasnAPI/Validators/UserValidator.cs | 37 ++++++++++++++++--- 9 files changed, 109 insertions(+), 8 deletions(-) diff --git a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs index a343a508..08aa4c60 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs @@ -1,5 +1,6 @@ using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; +using System.Text.RegularExpressions; namespace ReasnAPI.Validators { @@ -17,6 +18,11 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("City is too long", [nameof(address.City)]); } + if (new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{Lu}\\p{Ll}+)*$").IsMatch(address.City) is false) + { + yield return new ValidationResult("City is invalid", [nameof(address.City)]); + } + if (string.IsNullOrWhiteSpace(address.Country)) { yield return new ValidationResult("Country is required", [nameof(address.Country)]); @@ -27,6 +33,11 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("Country is too long", [nameof(address.Country)]); } + if (new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)(\\p{Lu}\\p{Ll}+|i|of|and|the)){0,5}$").IsMatch(address.Country) is false) + { + yield return new ValidationResult("Country is invalid", [nameof(address.Country)]); + } + if (string.IsNullOrWhiteSpace(address.Street)) { yield return new ValidationResult("Street is required", [nameof(address.Street)]); @@ -37,6 +48,11 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("Street is too long", [nameof(address.Street)]); } + if (new Regex("^[\\p{L}\\d]+(?:(\\s)\\p{L}+)*(\\s(?:(\\d+\\p{L}?(/\\d*\\p{L}?)?)))?$").IsMatch(address.Street) is false) + { + yield return new ValidationResult("Street is invalid", [nameof(address.Street)]); + } + if (string.IsNullOrWhiteSpace(address.State)) { yield return new ValidationResult("State is required", [nameof(address.State)]); @@ -47,9 +63,22 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("State is too long", [nameof(address.State)]); } - if (!string.IsNullOrWhiteSpace(address.ZipCode) && address.ZipCode.Length > 8 ) + if (new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{L}+)*$").IsMatch(address.State) is false) + { + yield return new ValidationResult("State is invalid", [nameof(address.State)]); + } + + if (!string.IsNullOrWhiteSpace(address.ZipCode)) { - yield return new ValidationResult("ZipCode is too long", [nameof(address.ZipCode)]); + if (address.ZipCode.Length > 8) + { + yield return new ValidationResult("ZipCode is too long", [nameof(address.ZipCode)]); + } + + if (new Regex("^[\\p{L}\\d\\s-]{3,}$").IsMatch(address.ZipCode) is false) + { + yield return new ValidationResult("ZipCode is invalid", [nameof(address.ZipCode)]); + } } } } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs index 5cb71047..87de07e9 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs @@ -1,5 +1,6 @@ using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; +using System.Text.RegularExpressions; namespace ReasnAPI.Validators { @@ -72,6 +73,11 @@ public static IEnumerable Validate(Event eventData) yield return new ValidationResult("Slug is too long", [nameof(eventData.Slug)]); } + if (new Regex("^[\\p{L}\\d]+[\\p{L}\\d-]*$").IsMatch(eventData.Slug)) + { + yield return new ValidationResult("Slug is invalid", [nameof(eventData.Name)]); + } + if (string.IsNullOrWhiteSpace(eventData.StatusId.ToString())) { yield return new ValidationResult("StatusId is required", [nameof(eventData.StatusId)]); diff --git a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs index 4729cb1e..ce4704ed 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs @@ -1,5 +1,6 @@ using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; +using System.Text.RegularExpressions; namespace ReasnAPI.Validators { @@ -16,6 +17,11 @@ public static IEnumerable Validate(Interest interest) { yield return new ValidationResult("Name is too long", [nameof(interest.Name)]); } + + if (new Regex("^\\p{Lu}\\p{Ll}+(?:\\s\\p{L}+)*$").IsMatch(interest.Name)) + { + yield return new ValidationResult("Name is invalid", [nameof(interest.Name)]); + } } } } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs index db634df6..c26bddaf 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs @@ -1,5 +1,6 @@ using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; +using System.Text.RegularExpressions; namespace ReasnAPI.Validators { @@ -16,6 +17,11 @@ public static IEnumerable Validate(ObjectType objectType) { yield return new ValidationResult("Name is too long", [nameof(objectType.Name)]); } + + if (new Regex("^(Event|User)$").IsMatch(objectType.Name) is false) + { + yield return new ValidationResult("Name is invalid", [nameof(objectType.Name)]); + } } } } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs index b5271925..8a06fe21 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs @@ -1,5 +1,6 @@ using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; +using System.Text.RegularExpressions; namespace ReasnAPI.Validators { @@ -17,6 +18,11 @@ public static IEnumerable Validate(Parameter parameter) yield return new ValidationResult("Key is too long", [nameof(parameter.Key)]); } + if (new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(parameter.Key)) + { + yield return new ValidationResult("Key is invalid", [nameof(parameter.Key)]); + } + if (string.IsNullOrWhiteSpace(parameter.Value)) { yield return new ValidationResult("Value is required", [nameof(parameter.Value)]); @@ -26,6 +32,11 @@ public static IEnumerable Validate(Parameter parameter) { yield return new ValidationResult("Value is too long", [nameof(parameter.Value)]); } + + if (new Regex("^[\\p{L}\\d]+(?:\\s[\\p{L}\\d]+)*$").IsMatch(parameter.Value)) + { + yield return new ValidationResult("Value is invalid", [nameof(parameter.Value)]); + } } } } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs index 119b2f9d..362a9fc9 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs @@ -1,5 +1,6 @@ using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; +using System.Text.RegularExpressions; namespace ReasnAPI.Validators { @@ -16,6 +17,11 @@ public static IEnumerable Validate(Role role) { yield return new ValidationResult("Role name is too long", [nameof(role.Name)]); } + + if (new Regex("^(Organizer|Admin|User)$").IsMatch(role.Name) is false) + { + yield return new ValidationResult("Role name is invalid", [nameof(role.Name)]); + } } } } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs index 579f0faa..a28e7bb1 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs @@ -1,5 +1,6 @@ using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; +using System.Text.RegularExpressions; namespace ReasnAPI.Validators { @@ -21,6 +22,11 @@ public static IEnumerable Validate(Status status) { yield return new ValidationResult("ObjectTypeId is required", [nameof(status.ObjectTypeId)]); } + + if (new Regex("^(Interested|Participating|Completed|In progress|Waiting for approval)$").IsMatch(status.Name) is false) + { + yield return new ValidationResult("Name is invalid", [nameof(status.Name)]); + } } } } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs index ecae1929..ff7ee67c 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs @@ -1,5 +1,6 @@ using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; +using System.Text.RegularExpressions; namespace ReasnAPI.Validators { @@ -16,6 +17,11 @@ public static IEnumerable Validate(Tag tag) { yield return new ValidationResult("Name is too long", [nameof(tag.Name)]); } + + if (new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(tag.Name)) + { + yield return new ValidationResult("Name is invalid", [nameof(tag.Name)]); + } } } } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs index 56da2983..b6dfb0d0 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs @@ -1,5 +1,6 @@ using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; +using System.Text.RegularExpressions; namespace ReasnAPI.Validators { @@ -17,6 +18,11 @@ public static IEnumerable Validate(User user) yield return new ValidationResult("Name is too long", [nameof(user.Name)]); } + if (new Regex("^\\p{Lu}\\p{Ll}+$").IsMatch(user.Name) is false) + { + yield return new ValidationResult("Name is invalid", [nameof(user.Name)]); + } + if (string.IsNullOrWhiteSpace(user.Surname)) { yield return new ValidationResult("Surname is required", [nameof(user.Surname)]); @@ -27,6 +33,11 @@ public static IEnumerable Validate(User user) yield return new ValidationResult("Surname is too long", [nameof(user.Surname)]); } + if (new Regex("^\\p{L}+(?:[\\s'-]?\\p{L}+)*$").IsMatch(user.Surname) is false) + { + yield return new ValidationResult("Surname is invalid", [nameof(user.Surname)]); + } + if (string.IsNullOrWhiteSpace(user.Username)) { yield return new ValidationResult("Username is required", [nameof(user.Username)]); @@ -37,6 +48,11 @@ public static IEnumerable Validate(User user) yield return new ValidationResult("Username is too long", [nameof(user.Username)]); } + if (new Regex("^[\\p{L}\\d._%+-]+$").IsMatch(user.Username) is false) + { + yield return new ValidationResult("Username is invalid", [nameof(user.Username)]); + } + if (string.IsNullOrWhiteSpace(user.Password)) { yield return new ValidationResult("Password is required", [nameof(user.Password)]); @@ -67,20 +83,29 @@ public static IEnumerable Validate(User user) yield return new ValidationResult("Email is too long", [nameof(user.Email)]); } - if (string.IsNullOrWhiteSpace(user.AddressId.ToString())) + if (new Regex("^[a-zA-Z\\d._%+-]+@[a-zA-Z\\d.-]+\\.[a-zA-Z]{2,6}$").IsMatch(user.Email) is false) { - yield return new ValidationResult("AddressId is required", [nameof(user.AddressId)]); + yield return new ValidationResult("Email is invalid", [nameof(user.Email)]); } - if (string.IsNullOrWhiteSpace(user.Phone)) + if (string.IsNullOrWhiteSpace(user.AddressId.ToString())) { - yield return new ValidationResult("Phone is required", [nameof(user.Phone)]); + yield return new ValidationResult("AddressId is required", [nameof(user.AddressId)]); } - if (!string.IsNullOrWhiteSpace(user.Phone) && user.Phone.Length > 16) + if (!string.IsNullOrWhiteSpace(user.Phone)) { - yield return new ValidationResult("Phone is too long", [nameof(user.Phone)]); + if (!string.IsNullOrWhiteSpace(user.Phone) && user.Phone.Length > 16) + { + yield return new ValidationResult("Phone is too long", [nameof(user.Phone)]); + } + + if (new Regex("^\\+\\d{1,3}\\s\\d{1,15}$").IsMatch(user.Phone) is false) + { + yield return new ValidationResult("Phone is invalid", [nameof(user.Phone)]); + } } + } } } From b2825e863a91296d5906b3b2bbaf0c7eb927a5db Mon Sep 17 00:00:00 2001 From: Maciej Koperdowski Date: Mon, 13 May 2024 19:49:10 +0200 Subject: [PATCH 03/24] Added regex in validators, changed models into dtos, created unit tests --- .../ReasnAPI.Tests/ReasnAPI.Tests.csproj | 4 + Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs | 12 - .../Validators/AddressValidatorTests.cs | 336 ++++++++++++++++ .../Validators/CommentValidatorTests.cs | 65 +++ .../Validators/EventValidatorTests.cs | 257 ++++++++++++ .../Validators/InterestValidatorTests.cs | 62 +++ .../Validators/ObjectTypeValidatorTests.cs | 75 ++++ .../Validators/ParameterValidatorTests.cs | 109 +++++ .../Validators/RoleValidatorTests.cs | 75 ++++ .../Validators/StatusValidatorTests.cs | 101 +++++ .../Validators/TagValidatorTests.cs | 62 +++ .../Validators/UserValidatorTests.cs | 374 ++++++++++++++++++ .../ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs | 2 +- Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj | 1 - .../ReasnAPI/Validators/AddressValidator.cs | 16 +- .../ReasnAPI/Validators/CommentValidator.cs | 24 +- .../ReasnAPI/Validators/EventValidator.cs | 41 +- .../ReasnAPI/Validators/ImageValidator.cs | 21 - .../ReasnAPI/Validators/InterestValidator.cs | 8 +- .../Validators/ObjectTypeValidator.cs | 2 +- .../ReasnAPI/Validators/ParameterValidator.cs | 10 +- .../ReasnAPI/Validators/RoleValidator.cs | 13 +- .../ReasnAPI/Validators/StatusValidator.cs | 18 +- .../ReasnAPI/Validators/TagValidator.cs | 8 +- .../ReasnAPI/Validators/UserValidator.cs | 43 +- 25 files changed, 1572 insertions(+), 167 deletions(-) delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/AddressValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs diff --git a/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj b/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj index 1b46a3ed..44463a72 100644 --- a/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj +++ b/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj @@ -17,6 +17,10 @@ + + + + diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs deleted file mode 100644 index 46dac6f2..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace ReasnAPI.Tests -{ - [TestClass] - public class UnitTest1 - { - [TestMethod] - public void TestAdd() - { - Assert.AreEqual(17, 17); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/AddressValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/AddressValidatorTests.cs new file mode 100644 index 00000000..0ff447ab --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/AddressValidatorTests.cs @@ -0,0 +1,336 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class AddressValidatorTests + { + [TestMethod] + public void Validate_WhenCityIsEmpty_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "", + Country = "Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "City is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "City is invalid")); + } + + [TestMethod] + public void Validate_WhenCityIsTooLong_ReturnsValidationResult() + { + var address = new AddressDto + { + City = new string('a', 65), + Country = "Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "City is too long")); + } + + [TestMethod] + public void Validate_WhenCityIsInvalid_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "Invalid City", + Country = "Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "City is invalid")); + } + + [TestMethod] + public void Validate_WhenCityIsValid_ReturnsNoValidationResult() + { + var address = new AddressDto + { + City = "Valid City", + Country = "Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenCountryIsEmpty_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Country is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Country is invalid")); + } + + [TestMethod] + public void Validate_WhenCountryIsTooLong_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = new string('a', 65), + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Country is too long")); + } + + [TestMethod] + public void Validate_WhenCountryIsInvalid_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Invalid Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Country is invalid")); + } + + [TestMethod] + public void Validate_WhenCountryIsValid_ReturnsNoValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Valid Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenStreetIsEmpty_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Street is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Street is invalid")); + } + + [TestMethod] + public void Validate_WhenStreetIsTooLong_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = new string('a', 65), + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Street is too long")); + } + + [TestMethod] + public void Validate_WhenStreetIsInvalid_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Invalid Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Street is invalid")); + } + + [TestMethod] + public void Validate_WhenStreetIsValid_ReturnsNoValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Valid Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenStateIsEmpty_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = "", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "State is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "State is invalid")); + } + + [TestMethod] + public void Validate_WhenStateIsTooLong_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = new string('a', 65), + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "State is too long")); + } + + [TestMethod] + public void Validate_WhenStateIsInvalid_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = "Invalid State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "State is invalid")); + } + + [TestMethod] + public void Validate_WhenStateIsValid_ReturnsNoValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = "Valid State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Valdate_WhenZipCodeIsTooLong_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = "State", + ZipCode = new string('0', 9) + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "ZipCode is too long")); + } + + [TestMethod] + public void Validate_WhenZipCodeIsInvalid_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = "State", + ZipCode = "Invalid_" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "ZipCode is invalid")); + } + + [TestMethod] + public void Validate_WhenZipCodeIsValid_ReturnsNoValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsFalse(result.Any()); + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs new file mode 100644 index 00000000..49f64da6 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs @@ -0,0 +1,65 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class CommentValidatorTests + { + [TestMethod] + public void Validate_WhenContentIsEmpty_ReturnsValidationResult() + { + var comment = new CommentDto + { + Content = "", + CreatedAt = DateTime.Now + }; + + var result = CommentValidator.Validate(comment); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Content is required")); + } + + [TestMethod] + public void Validate_WhenContentIsTooLong_ReturnsValidationResult() + { + var comment = new CommentDto + { + Content = new string('a', 1025), + CreatedAt = DateTime.Now + }; + + var result = CommentValidator.Validate(comment); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Content is too long")); + } + + [TestMethod] + public void Validate_WhenCreatedAtIsInTheFuture_ReturnsValidationResult() + { + var comment = new CommentDto + { + Content = "Content", + CreatedAt = DateTime.Now.AddMinutes(1) + }; + + var result = CommentValidator.Validate(comment); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "CreatedAt is in the future")); + } + + [TestMethod] + public void Validate_WhenCommentIsValid_ReturnsNoValidationResult() + { + var comment = new CommentDto + { + Content = "Content", + CreatedAt = DateTime.Now + }; + + var result = CommentValidator.Validate(comment); + + Assert.IsFalse(result.Any()); + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs new file mode 100644 index 00000000..ce6b68ff --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs @@ -0,0 +1,257 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class EventValidatorTests + { + [TestMethod] + public void Validate_WhenNameIsEmpty_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); + } + + [TestMethod] + public void Validate_WhenNameIsTooLong_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = new string('a', 65), + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); + } + + [TestMethod] + public void Validate_WhenNameIsValid_ReturnsNoValidationResult() + { + var event1 = new EventDto + { + Name = "ValidName", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenDescriptionIsEmpty_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Description is required")); + } + + [TestMethod] + public void Validate_WhenDescriptionIsTooLong_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = new string('a', 4049), + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Description is too long")); + } + + [TestMethod] + public void Validate_WhenDescriptionIsValid_ReturnsNoValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Valid Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenStartAtIsAfterEndAt_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now.AddMinutes(1), + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "StartTime is after EndTime")); + } + + [TestMethod] + public void Validate_WhenCreatedAtIsInTheFuture_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now.AddMinutes(1), + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "CreatedAt is in the future")); + } + + [TestMethod] + public void Validate_WhenUpdatedAtIsInTheFuture_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now.AddMinutes(1), + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "UpdatedAt is in the future")); + } + + [TestMethod] + public void Validate_WhenSlugIsEmpty_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is invalid")); + } + + [TestMethod] + public void Validate_WhenSlugIsTooLong_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = new string('a', 129) + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is too long")); + } + + [TestMethod] + public void Validate_WhenSlugIsIsInvalid_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "invalid slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is invalid")); + } + + [TestMethod] + public void Validate_WhenSlugIsValid_ReturnsNoValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "valid-slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsFalse(result.Any()); + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs new file mode 100644 index 00000000..4d64732a --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs @@ -0,0 +1,62 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class InterestValidatorTests + { + [TestMethod] + public void Validate_WhenNameIsEmpty_ReturnsValidationResult() + { + var interest = new IntrestDto + { + Name = "" + }; + + var result = InterestValidator.Validate(interest); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsTooLong_ReturnsValidationResult() + { + var interest = new IntrestDto + { + Name = new string('a', 33) + }; + + var result = InterestValidator.Validate(interest); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); + } + + [TestMethod] + public void Validate_WhenNameIsInvalid_ReturnsValidationResult() + { + var interest = new IntrestDto + { + Name = "Invalid Name" + }; + + var result = InterestValidator.Validate(interest); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsValid_ReturnsNoValidationResult() + { + var interest = new IntrestDto + { + Name = "Valid Name" + }; + + var result = InterestValidator.Validate(interest); + + Assert.IsFalse(result.Any()); + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs new file mode 100644 index 00000000..5c1480ee --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs @@ -0,0 +1,75 @@ +using ReasnAPI.Models.Database; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class ObjectTypeValidatorTests + { + [TestMethod] + public void Validate_WhenNameIsEmpty_ReturnsValidationResult() + { + var objectType = new ObjectType + { + Name = "" + }; + + var result = ObjectTypeValidator.Validate(objectType); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsTooLong_ReturnsValidationResult() + { + var objectType = new ObjectType + { + Name = new string('a', 33) + }; + + var result = ObjectTypeValidator.Validate(objectType); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); + } + + [TestMethod] + public void Validate_WhenNameIsInvalid_ReturnsValidationResult() + { + var objectType = new ObjectType + { + Name = "Invalid Name" + }; + + var result = ObjectTypeValidator.Validate(objectType); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsEvent_ReturnsNoValidationResult() + { + var objectType = new ObjectType + { + Name = "Event" + }; + + var result = ObjectTypeValidator.Validate(objectType); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenNameIsUser_ReturnsNoValidationResult() + { + var objectType = new ObjectType + { + Name = "User" + }; + + var result = ObjectTypeValidator.Validate(objectType); + + Assert.IsFalse(result.Any()); + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs new file mode 100644 index 00000000..424f987b --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs @@ -0,0 +1,109 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class ParameterValidatorTests + { + [TestMethod] + public void Validate_WhenKeyIsEmpty_ReturnsKeyIsRequired() + { + var parameter = new ParameterDto + { + Key = "", + Value = "value" + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is invalid")); + } + + [TestMethod] + public void Validate_WhenKeyIsTooLong_ReturnsKeyIsTooLong() + { + var parameter = new ParameterDto + { + Key = new string('a', 33), + Value = "value" + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is too long")); + } + + [TestMethod] + public void Validate_WhenKeyIsInvalid_ReturnsKeyIsInvalid() + { + var parameter = new ParameterDto + { + Key = "Invalid Key", + Value = "value" + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is invalid")); + } + + [TestMethod] + public void Validate_WhenValueIsEmpty_ReturnsValueIsRequired() + { + var parameter = new ParameterDto + { + Key = "key", + Value = "" + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is invalid")); + } + + [TestMethod] + public void Validate_WhenValueIsTooLong_ReturnsValueIsTooLong() + { + var parameter = new ParameterDto + { + Key = "key", + Value = new string('a', 65) + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is too long")); + } + + [TestMethod] + public void Validate_WhenValueIsInvalid_ReturnsValueIsInvalid() + { + var parameter = new ParameterDto + { + Key = "key", + Value = "Invalid Value" + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is invalid")); + } + + [TestMethod] + public void Validate_WhenValueAndKeyAreValid_ReturnsNoValidationResult() + { + var parameter = new ParameterDto + { + Key = "key", + Value = "value" + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsFalse(result.Any()); + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs new file mode 100644 index 00000000..a662254a --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs @@ -0,0 +1,75 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class RoleValidatorTests + { + [TestMethod] + public void Validate_WhenRoleNameIsEmpty_ReturnsValidationResult() + { + var role = new RoleDto + { + Name = "" + }; + + var result = RoleValidator.Validate(role); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Role name is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Role name is invalid")); + } + + [TestMethod] + public void Validate_WhenRoleNameIsInvalid_ReturnsValidationResult() + { + var role = new RoleDto + { + Name = "Invalid Role" + }; + + var result = RoleValidator.Validate(role); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Role name is invalid")); + } + + [TestMethod] + public void Validate_WhenRoleNameIsOrganizer_ReturnsNoValidationResult() + { + var role = new RoleDto + { + Name = "Organizer" + }; + + var result = RoleValidator.Validate(role); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenRoleNameIsAdmin_ReturnsNoValidationResult() + { + var role = new RoleDto + { + Name = "Admin" + }; + + var result = RoleValidator.Validate(role); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenRoleNameIsUser_ReturnsNoValidationResult() + { + var role = new RoleDto + { + Name = "User" + }; + + var result = RoleValidator.Validate(role); + + Assert.IsFalse(result.Any()); + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs new file mode 100644 index 00000000..c3438cdf --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs @@ -0,0 +1,101 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class StatusValidatorTests + { + [TestMethod] + public void Validate_WhenNameIsEmpty_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsInvalid_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "Invalid Name" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsInterested_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "Interested" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsParticipating_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "Participating" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsCompleted_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "Completed" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsInProgress_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "In progress" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsWaitingForApproval_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "Waiting for approval" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs new file mode 100644 index 00000000..4a935bdd --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs @@ -0,0 +1,62 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class TagValidatorTests + { + [TestMethod] + public void Validate_WhenNameIsEmpty_ReturnsValidationResult() + { + var tag = new TagDto + { + Name = "" + }; + + var result = TagValidator.Validate(tag); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsTooLong_ReturnsValidationResult() + { + var tag = new TagDto + { + Name = new string('a', 65) + }; + + var result = TagValidator.Validate(tag); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); + } + + [TestMethod] + public void Validate_WhenNameIsInvalid_ReturnsValidationResult() + { + var tag = new TagDto + { + Name = "Invalid Name" + }; + + var result = TagValidator.Validate(tag); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsValid_ReturnsValidationResult() + { + var tag = new TagDto + { + Name = "Valid Name" + }; + + var result = TagValidator.Validate(tag); + + Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs new file mode 100644 index 00000000..a5de2ecf --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs @@ -0,0 +1,374 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class UserValidatorTests + { + [TestMethod] + public void Validate_WhenNameIsEmpty_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsTooLong_ReturnsValidationResult() + { + var user = new UserDto + { + Name = new string('a', 65), + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); + } + + [TestMethod] + public void Validate_WhenNameIsInvalid_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Invalid Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsValid_ReturnsNoValidationResult() + { + var user = new UserDto + { + Name = "Validname", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenSurnameIsEmpty_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is invalid")); + } + + [TestMethod] + public void Validate_WhenSurnameIsTooLong_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = new string('a', 65), + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is too long")); + } + + [TestMethod] + public void Validate_WhenSurnameIsInvalid_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Invalid Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is invalid")); + } + + [TestMethod] + public void Validate_WhenSurnameIsValid_ReturnsNoValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Validsurname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenUsernameIsEmpty_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is invalid")); + } + + [TestMethod] + public void Validate_WhenUsernameIsTooLong_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = new string('a', 65), + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is too long")); + } + + [TestMethod] + public void Validate_WhenUsernameIsInvalid_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Invalid Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is invalid")); + } + + [TestMethod] + public void Validate_WhenUsernameIsValid_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "ValidUsername", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenEmailIsEmpty_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is invalid")); + } + + [TestMethod] + public void Validate_WhenEmailIsTooLong_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = new string('a', 256), + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is too long")); + } + + [TestMethod] + public void Validate_WhenEmailIsInvalid_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "Invalid Email", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is invalid")); + } + + [TestMethod] + public void Validate_WhenEmailIsValid_ReturnsNoValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "valid@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenPhoneIsTooLong_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = new string('a', 20) + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Phone is too long")); + } + + [TestMethod] + public void Validate_WhenPhoneIsInvalid_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "Invalid Phone" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Phone is invalid")); + } + + [TestMethod] + public void Validate_WhenPhoneIsValid_ReturnsNoValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsFalse(result.Any()); + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs b/Server/ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs index d35c8120..00c00ff5 100644 --- a/Server/ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs +++ b/Server/ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs @@ -10,7 +10,7 @@ public class EventDto { public DateTime EndAt { get; set; } public DateTime CreatedAt { get; set; } public DateTime UpdatedAt { get; set; } - public string? Slug { get; set; } + public string Slug { get; set; } = null!; public int StatusId { get; set; } public List? Tags { get; set; } } diff --git a/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj b/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj index 02ce3550..a5564cb9 100644 --- a/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj +++ b/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj @@ -23,7 +23,6 @@ - diff --git a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs index 08aa4c60..e6c9897c 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class AddressValidator : IValidator
+ public class AddressValidator : IValidator { - public static IEnumerable Validate(Address address) + public static IEnumerable Validate(AddressDto address) { if (string.IsNullOrWhiteSpace(address.City)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("City is too long", [nameof(address.City)]); } - if (new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{Lu}\\p{Ll}+)*$").IsMatch(address.City) is false) + if (!new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{Lu}\\p{Ll}+)*$").IsMatch(address.City)) { yield return new ValidationResult("City is invalid", [nameof(address.City)]); } @@ -33,7 +33,7 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("Country is too long", [nameof(address.Country)]); } - if (new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)(\\p{Lu}\\p{Ll}+|i|of|and|the)){0,5}$").IsMatch(address.Country) is false) + if (!new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)(\\p{Lu}\\p{Ll}+|i|of|and|the)){0,5}$").IsMatch(address.Country)) { yield return new ValidationResult("Country is invalid", [nameof(address.Country)]); } @@ -48,7 +48,7 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("Street is too long", [nameof(address.Street)]); } - if (new Regex("^[\\p{L}\\d]+(?:(\\s)\\p{L}+)*(\\s(?:(\\d+\\p{L}?(/\\d*\\p{L}?)?)))?$").IsMatch(address.Street) is false) + if (!new Regex("^[\\p{L}\\d]+(?:(\\s)\\p{L}+)*(\\s(?:(\\d+\\p{L}?(/\\d*\\p{L}?)?)))?$").IsMatch(address.Street)) { yield return new ValidationResult("Street is invalid", [nameof(address.Street)]); } @@ -63,7 +63,7 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("State is too long", [nameof(address.State)]); } - if (new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{L}+)*$").IsMatch(address.State) is false) + if (!new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{L}+)*$").IsMatch(address.State)) { yield return new ValidationResult("State is invalid", [nameof(address.State)]); } @@ -75,7 +75,7 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("ZipCode is too long", [nameof(address.ZipCode)]); } - if (new Regex("^[\\p{L}\\d\\s-]{3,}$").IsMatch(address.ZipCode) is false) + if (!new Regex("^[\\p{L}\\d\\s-]{3,}$").IsMatch(address.ZipCode)) { yield return new ValidationResult("ZipCode is invalid", [nameof(address.ZipCode)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs index e4fd2264..54a68c45 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs @@ -1,18 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; -using System.Numerics; namespace ReasnAPI.Validators { - public class CommentValidator : IValidator + public class CommentValidator : IValidator { - public static IEnumerable Validate(Comment comment) + public static IEnumerable Validate(CommentDto comment) { - if (string.IsNullOrWhiteSpace(comment.EventId.ToString())) - { - yield return new ValidationResult("EventId is required", [nameof(comment.EventId)]); - } - if (string.IsNullOrWhiteSpace(comment.Content)) { yield return new ValidationResult("Content is required", [nameof(comment.Content)]); @@ -23,20 +17,10 @@ public static IEnumerable Validate(Comment comment) yield return new ValidationResult("Content is too long", [nameof(comment.Content)]); } - if (string.IsNullOrWhiteSpace(comment.CreatedAt.ToString())) - { - yield return new ValidationResult("CreatedAt is required", [nameof(comment.CreatedAt)]); - } - - if (comment.CreatedAt > DateTime.Now) + if (comment.CreatedAt >= DateTime.Now) { yield return new ValidationResult("CreatedAt is in the future", [nameof(comment.CreatedAt)]); } - - if (string.IsNullOrWhiteSpace(comment.UserId.ToString())) - { - yield return new ValidationResult("UserId is required", [nameof(comment.UserId)]); - } } } } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs index 87de07e9..f86f601c 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class EventValidator : IValidator + public class EventValidator : IValidator { - public static IEnumerable Validate(Event eventData) + public static IEnumerable Validate(EventDto eventData) { if (string.IsNullOrWhiteSpace(eventData.Name)) { @@ -18,11 +18,6 @@ public static IEnumerable Validate(Event eventData) yield return new ValidationResult("Name is too long", [nameof(eventData.Name)]); } - if (string.IsNullOrWhiteSpace(eventData.AddressId.ToString())) - { - yield return new ValidationResult("AddressId is required", [nameof(eventData.AddressId)]); - } - if (string.IsNullOrWhiteSpace(eventData.Description)) { yield return new ValidationResult("Description is required", [nameof(eventData.Description)]); @@ -33,34 +28,19 @@ public static IEnumerable Validate(Event eventData) yield return new ValidationResult("Description is too long", [nameof(eventData.Description)]); } - if (string.IsNullOrWhiteSpace(eventData.OrganizerId.ToString())) - { - yield return new ValidationResult("OrganizerId is required", [nameof(eventData.OrganizerId)]); - } - - if (string.IsNullOrWhiteSpace(eventData.StartAt.ToString())) - { - yield return new ValidationResult("StartTime is required", [nameof(eventData.StartAt)]); - } - - if (string.IsNullOrWhiteSpace(eventData.EndAt.ToString())) - { - yield return new ValidationResult("EndTime is required", [nameof(eventData.EndAt)]); - } - if (eventData.StartAt > eventData.EndAt) { yield return new ValidationResult("StartTime is after EndTime", [nameof(eventData.StartAt)]); } - if (string.IsNullOrWhiteSpace(eventData.CreatedAt.ToString())) + if (eventData.CreatedAt >= DateTime.Now) { - yield return new ValidationResult("CreatedAt is required", [nameof(eventData.CreatedAt)]); + yield return new ValidationResult("CreatedAt is in the future", [nameof(eventData.CreatedAt)]); } - if (string.IsNullOrWhiteSpace(eventData.UpdatedAt.ToString())) + if (eventData.UpdatedAt >= DateTime.Now) { - yield return new ValidationResult("UpdatedAt is required", [nameof(eventData.UpdatedAt)]); + yield return new ValidationResult("UpdatedAt is in the future", [nameof(eventData.UpdatedAt)]); } if (string.IsNullOrWhiteSpace(eventData.Slug)) @@ -73,15 +53,10 @@ public static IEnumerable Validate(Event eventData) yield return new ValidationResult("Slug is too long", [nameof(eventData.Slug)]); } - if (new Regex("^[\\p{L}\\d]+[\\p{L}\\d-]*$").IsMatch(eventData.Slug)) + if (!new Regex("^[\\p{L}\\d]+[\\p{L}\\d-]*$").IsMatch(eventData.Slug)) { yield return new ValidationResult("Slug is invalid", [nameof(eventData.Name)]); } - - if (string.IsNullOrWhiteSpace(eventData.StatusId.ToString())) - { - yield return new ValidationResult("StatusId is required", [nameof(eventData.StatusId)]); - } } } } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs deleted file mode 100644 index 15de2bfc..00000000 --- a/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs +++ /dev/null @@ -1,21 +0,0 @@ -using ReasnAPI.Models.Database; -using System.ComponentModel.DataAnnotations; - -namespace ReasnAPI.Validators -{ - public class ImageValidator : IValidator - { - public static IEnumerable Validate(Image image) - { - if (string.IsNullOrWhiteSpace(image.ObjectTypeId.ToString())) - { - yield return new ValidationResult("ObjectTypeId is required", [nameof(image.ObjectTypeId)]); - } - - if (string.IsNullOrWhiteSpace(image.ObjectId.ToString())) - { - yield return new ValidationResult("ObjectId is required", [nameof(image.ObjectId)]); - } - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs index ce4704ed..d6068f0b 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class InterestValidator : IValidator + public class InterestValidator : IValidator { - public static IEnumerable Validate(Interest interest) + public static IEnumerable Validate(IntrestDto interest) { if (string.IsNullOrWhiteSpace(interest.Name)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(Interest interest) yield return new ValidationResult("Name is too long", [nameof(interest.Name)]); } - if (new Regex("^\\p{Lu}\\p{Ll}+(?:\\s\\p{L}+)*$").IsMatch(interest.Name)) + if (!new Regex("^\\p{Lu}\\p{Ll}+(?:\\s\\p{L}+)*$").IsMatch(interest.Name)) { yield return new ValidationResult("Name is invalid", [nameof(interest.Name)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs index c26bddaf..e2e965ce 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs @@ -18,7 +18,7 @@ public static IEnumerable Validate(ObjectType objectType) yield return new ValidationResult("Name is too long", [nameof(objectType.Name)]); } - if (new Regex("^(Event|User)$").IsMatch(objectType.Name) is false) + if (!new Regex("^(Event|User)$").IsMatch(objectType.Name)) { yield return new ValidationResult("Name is invalid", [nameof(objectType.Name)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs index 8a06fe21..42ad28fa 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class ParameterValidator : IValidator + public class ParameterValidator : IValidator { - public static IEnumerable Validate(Parameter parameter) + public static IEnumerable Validate(ParameterDto parameter) { if (string.IsNullOrWhiteSpace(parameter.Key)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(Parameter parameter) yield return new ValidationResult("Key is too long", [nameof(parameter.Key)]); } - if (new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(parameter.Key)) + if (!new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(parameter.Key)) { yield return new ValidationResult("Key is invalid", [nameof(parameter.Key)]); } @@ -33,7 +33,7 @@ public static IEnumerable Validate(Parameter parameter) yield return new ValidationResult("Value is too long", [nameof(parameter.Value)]); } - if (new Regex("^[\\p{L}\\d]+(?:\\s[\\p{L}\\d]+)*$").IsMatch(parameter.Value)) + if (!new Regex("^[\\p{L}\\d]+(?:\\s[\\p{L}\\d]+)*$").IsMatch(parameter.Value)) { yield return new ValidationResult("Value is invalid", [nameof(parameter.Value)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs index 362a9fc9..83712151 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs @@ -1,24 +1,19 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class RoleValidator : IValidator + public class RoleValidator : IValidator { - public static IEnumerable Validate(Role role) + public static IEnumerable Validate(RoleDto role) { if (string.IsNullOrWhiteSpace(role.Name)) { yield return new ValidationResult("Role name is required", [nameof(role.Name)]); } - if (role.Name.Length > 32) - { - yield return new ValidationResult("Role name is too long", [nameof(role.Name)]); - } - - if (new Regex("^(Organizer|Admin|User)$").IsMatch(role.Name) is false) + if (!new Regex("^(Organizer|Admin|User)$").IsMatch(role.Name)) { yield return new ValidationResult("Role name is invalid", [nameof(role.Name)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs index a28e7bb1..680a6e0d 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs @@ -1,29 +1,19 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class StatusValidator : IValidator + public class StatusValidator : IValidator { - public static IEnumerable Validate(Status status) + public static IEnumerable Validate(StatusDto status) { if (string.IsNullOrWhiteSpace(status.Name)) { yield return new ValidationResult("Name is required", [nameof(status.Name)]); } - if (status.Name.Length > 32) - { - yield return new ValidationResult("Name is too long", [nameof(status.Name)]); - } - - if (string.IsNullOrWhiteSpace(status.ObjectTypeId.ToString())) - { - yield return new ValidationResult("ObjectTypeId is required", [nameof(status.ObjectTypeId)]); - } - - if (new Regex("^(Interested|Participating|Completed|In progress|Waiting for approval)$").IsMatch(status.Name) is false) + if (!new Regex("^(Interested|Participating|Completed|In progress|Waiting for approval)$").IsMatch(status.Name)) { yield return new ValidationResult("Name is invalid", [nameof(status.Name)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs index ff7ee67c..10c45944 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class TagValidator : IValidator + public class TagValidator : IValidator { - public static IEnumerable Validate(Tag tag) + public static IEnumerable Validate(TagDto tag) { if (string.IsNullOrWhiteSpace(tag.Name)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(Tag tag) yield return new ValidationResult("Name is too long", [nameof(tag.Name)]); } - if (new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(tag.Name)) + if (!new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(tag.Name)) { yield return new ValidationResult("Name is invalid", [nameof(tag.Name)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs index b6dfb0d0..2e153655 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class UserValidator : IValidator + public class UserValidator : IValidator { - public static IEnumerable Validate(User user) + public static IEnumerable Validate(UserDto user) { if (string.IsNullOrWhiteSpace(user.Name)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(User user) yield return new ValidationResult("Name is too long", [nameof(user.Name)]); } - if (new Regex("^\\p{Lu}\\p{Ll}+$").IsMatch(user.Name) is false) + if (!new Regex("^\\p{Lu}\\p{Ll}+$").IsMatch(user.Name)) { yield return new ValidationResult("Name is invalid", [nameof(user.Name)]); } @@ -33,7 +33,7 @@ public static IEnumerable Validate(User user) yield return new ValidationResult("Surname is too long", [nameof(user.Surname)]); } - if (new Regex("^\\p{L}+(?:[\\s'-]?\\p{L}+)*$").IsMatch(user.Surname) is false) + if (!new Regex("^\\p{L}+(?:[\\s'-]?\\p{L}+)*$").IsMatch(user.Surname)) { yield return new ValidationResult("Surname is invalid", [nameof(user.Surname)]); } @@ -48,31 +48,11 @@ public static IEnumerable Validate(User user) yield return new ValidationResult("Username is too long", [nameof(user.Username)]); } - if (new Regex("^[\\p{L}\\d._%+-]+$").IsMatch(user.Username) is false) + if (!new Regex("^[\\p{L}\\d._%+-]+$").IsMatch(user.Username)) { yield return new ValidationResult("Username is invalid", [nameof(user.Username)]); } - if (string.IsNullOrWhiteSpace(user.Password)) - { - yield return new ValidationResult("Password is required", [nameof(user.Password)]); - } - - if (string.IsNullOrWhiteSpace(user.CreatedAt.ToString())) - { - yield return new ValidationResult("CreatedAt is required", [nameof(user.CreatedAt)]); - } - - if (string.IsNullOrWhiteSpace(user.UpdatedAt.ToString())) - { - yield return new ValidationResult("UpdatedAt is required", [nameof(user.UpdatedAt)]); - } - - if (string.IsNullOrWhiteSpace(user.RoleId.ToString())) - { - yield return new ValidationResult("RoleId is required", [nameof(user.RoleId)]); - } - if (string.IsNullOrWhiteSpace(user.Email)) { yield return new ValidationResult("Email is required", [nameof(user.Email)]); @@ -83,24 +63,19 @@ public static IEnumerable Validate(User user) yield return new ValidationResult("Email is too long", [nameof(user.Email)]); } - if (new Regex("^[a-zA-Z\\d._%+-]+@[a-zA-Z\\d.-]+\\.[a-zA-Z]{2,6}$").IsMatch(user.Email) is false) + if (!new Regex("^[a-zA-Z\\d._%+-]+@[a-zA-Z\\d.-]+\\.[a-zA-Z]{2,6}$").IsMatch(user.Email)) { yield return new ValidationResult("Email is invalid", [nameof(user.Email)]); } - if (string.IsNullOrWhiteSpace(user.AddressId.ToString())) - { - yield return new ValidationResult("AddressId is required", [nameof(user.AddressId)]); - } - if (!string.IsNullOrWhiteSpace(user.Phone)) { - if (!string.IsNullOrWhiteSpace(user.Phone) && user.Phone.Length > 16) + if (user.Phone.Length > 16) { yield return new ValidationResult("Phone is too long", [nameof(user.Phone)]); } - if (new Regex("^\\+\\d{1,3}\\s\\d{1,15}$").IsMatch(user.Phone) is false) + if (!new Regex("^\\+\\d{1,3}\\s\\d{1,15}$").IsMatch(user.Phone)) { yield return new ValidationResult("Phone is invalid", [nameof(user.Phone)]); } From 33a51b08fccae38210e562473615b965a02dca61 Mon Sep 17 00:00:00 2001 From: Maciej Koperdowski Date: Mon, 13 May 2024 19:57:30 +0200 Subject: [PATCH 04/24] Revert "Added regex in validators, changed models into dtos, created unit tests" This reverts commit b2825e863a91296d5906b3b2bbaf0c7eb927a5db. --- .../ReasnAPI.Tests/ReasnAPI.Tests.csproj | 4 - Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs | 12 + .../Validators/AddressValidatorTests.cs | 336 ---------------- .../Validators/CommentValidatorTests.cs | 65 --- .../Validators/EventValidatorTests.cs | 257 ------------ .../Validators/InterestValidatorTests.cs | 62 --- .../Validators/ObjectTypeValidatorTests.cs | 75 ---- .../Validators/ParameterValidatorTests.cs | 109 ----- .../Validators/RoleValidatorTests.cs | 75 ---- .../Validators/StatusValidatorTests.cs | 101 ----- .../Validators/TagValidatorTests.cs | 62 --- .../Validators/UserValidatorTests.cs | 374 ------------------ .../ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs | 2 +- Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj | 1 + .../ReasnAPI/Validators/AddressValidator.cs | 16 +- .../ReasnAPI/Validators/CommentValidator.cs | 24 +- .../ReasnAPI/Validators/EventValidator.cs | 41 +- .../ReasnAPI/Validators/ImageValidator.cs | 21 + .../ReasnAPI/Validators/InterestValidator.cs | 8 +- .../Validators/ObjectTypeValidator.cs | 2 +- .../ReasnAPI/Validators/ParameterValidator.cs | 10 +- .../ReasnAPI/Validators/RoleValidator.cs | 13 +- .../ReasnAPI/Validators/StatusValidator.cs | 18 +- .../ReasnAPI/Validators/TagValidator.cs | 8 +- .../ReasnAPI/Validators/UserValidator.cs | 43 +- 25 files changed, 167 insertions(+), 1572 deletions(-) create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/AddressValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs diff --git a/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj b/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj index 44463a72..1b46a3ed 100644 --- a/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj +++ b/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj @@ -17,10 +17,6 @@ - - - - diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs new file mode 100644 index 00000000..46dac6f2 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs @@ -0,0 +1,12 @@ +namespace ReasnAPI.Tests +{ + [TestClass] + public class UnitTest1 + { + [TestMethod] + public void TestAdd() + { + Assert.AreEqual(17, 17); + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/AddressValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/AddressValidatorTests.cs deleted file mode 100644 index 0ff447ab..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/AddressValidatorTests.cs +++ /dev/null @@ -1,336 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class AddressValidatorTests - { - [TestMethod] - public void Validate_WhenCityIsEmpty_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "", - Country = "Country", - Street = "Street", - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "City is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "City is invalid")); - } - - [TestMethod] - public void Validate_WhenCityIsTooLong_ReturnsValidationResult() - { - var address = new AddressDto - { - City = new string('a', 65), - Country = "Country", - Street = "Street", - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "City is too long")); - } - - [TestMethod] - public void Validate_WhenCityIsInvalid_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "Invalid City", - Country = "Country", - Street = "Street", - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "City is invalid")); - } - - [TestMethod] - public void Validate_WhenCityIsValid_ReturnsNoValidationResult() - { - var address = new AddressDto - { - City = "Valid City", - Country = "Country", - Street = "Street", - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenCountryIsEmpty_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "", - Street = "Street", - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Country is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Country is invalid")); - } - - [TestMethod] - public void Validate_WhenCountryIsTooLong_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = new string('a', 65), - Street = "Street", - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Country is too long")); - } - - [TestMethod] - public void Validate_WhenCountryIsInvalid_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Invalid Country", - Street = "Street", - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Country is invalid")); - } - - [TestMethod] - public void Validate_WhenCountryIsValid_ReturnsNoValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Valid Country", - Street = "Street", - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenStreetIsEmpty_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Country", - Street = "", - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Street is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Street is invalid")); - } - - [TestMethod] - public void Validate_WhenStreetIsTooLong_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Country", - Street = new string('a', 65), - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Street is too long")); - } - - [TestMethod] - public void Validate_WhenStreetIsInvalid_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Country", - Street = "Invalid Street", - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Street is invalid")); - } - - [TestMethod] - public void Validate_WhenStreetIsValid_ReturnsNoValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Country", - Street = "Valid Street", - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenStateIsEmpty_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Country", - Street = "Street", - State = "", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "State is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "State is invalid")); - } - - [TestMethod] - public void Validate_WhenStateIsTooLong_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Country", - Street = "Street", - State = new string('a', 65), - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "State is too long")); - } - - [TestMethod] - public void Validate_WhenStateIsInvalid_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Country", - Street = "Street", - State = "Invalid State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "State is invalid")); - } - - [TestMethod] - public void Validate_WhenStateIsValid_ReturnsNoValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Country", - Street = "Street", - State = "Valid State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Valdate_WhenZipCodeIsTooLong_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Country", - Street = "Street", - State = "State", - ZipCode = new string('0', 9) - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "ZipCode is too long")); - } - - [TestMethod] - public void Validate_WhenZipCodeIsInvalid_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Country", - Street = "Street", - State = "State", - ZipCode = "Invalid_" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "ZipCode is invalid")); - } - - [TestMethod] - public void Validate_WhenZipCodeIsValid_ReturnsNoValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Country", - Street = "Street", - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsFalse(result.Any()); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs deleted file mode 100644 index 49f64da6..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs +++ /dev/null @@ -1,65 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class CommentValidatorTests - { - [TestMethod] - public void Validate_WhenContentIsEmpty_ReturnsValidationResult() - { - var comment = new CommentDto - { - Content = "", - CreatedAt = DateTime.Now - }; - - var result = CommentValidator.Validate(comment); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Content is required")); - } - - [TestMethod] - public void Validate_WhenContentIsTooLong_ReturnsValidationResult() - { - var comment = new CommentDto - { - Content = new string('a', 1025), - CreatedAt = DateTime.Now - }; - - var result = CommentValidator.Validate(comment); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Content is too long")); - } - - [TestMethod] - public void Validate_WhenCreatedAtIsInTheFuture_ReturnsValidationResult() - { - var comment = new CommentDto - { - Content = "Content", - CreatedAt = DateTime.Now.AddMinutes(1) - }; - - var result = CommentValidator.Validate(comment); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "CreatedAt is in the future")); - } - - [TestMethod] - public void Validate_WhenCommentIsValid_ReturnsNoValidationResult() - { - var comment = new CommentDto - { - Content = "Content", - CreatedAt = DateTime.Now - }; - - var result = CommentValidator.Validate(comment); - - Assert.IsFalse(result.Any()); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs deleted file mode 100644 index ce6b68ff..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs +++ /dev/null @@ -1,257 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class EventValidatorTests - { - [TestMethod] - public void Validate_WhenNameIsEmpty_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "", - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "slug" - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); - } - - [TestMethod] - public void Validate_WhenNameIsTooLong_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = new string('a', 65), - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "slug" - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); - } - - [TestMethod] - public void Validate_WhenNameIsValid_ReturnsNoValidationResult() - { - var event1 = new EventDto - { - Name = "ValidName", - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "slug" - }; - - var result = EventValidator.Validate(event1); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenDescriptionIsEmpty_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "", - StartAt = DateTime.Now, - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "slug" - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Description is required")); - } - - [TestMethod] - public void Validate_WhenDescriptionIsTooLong_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = new string('a', 4049), - StartAt = DateTime.Now, - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "slug" - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Description is too long")); - } - - [TestMethod] - public void Validate_WhenDescriptionIsValid_ReturnsNoValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "Valid Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "slug" - }; - - var result = EventValidator.Validate(event1); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenStartAtIsAfterEndAt_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "Description", - StartAt = DateTime.Now.AddMinutes(1), - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "slug" - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "StartTime is after EndTime")); - } - - [TestMethod] - public void Validate_WhenCreatedAtIsInTheFuture_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now, - CreatedAt = DateTime.Now.AddMinutes(1), - UpdatedAt = DateTime.Now, - Slug = "slug" - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "CreatedAt is in the future")); - } - - [TestMethod] - public void Validate_WhenUpdatedAtIsInTheFuture_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now.AddMinutes(1), - Slug = "slug" - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "UpdatedAt is in the future")); - } - - [TestMethod] - public void Validate_WhenSlugIsEmpty_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "" - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is invalid")); - } - - [TestMethod] - public void Validate_WhenSlugIsTooLong_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = new string('a', 129) - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is too long")); - } - - [TestMethod] - public void Validate_WhenSlugIsIsInvalid_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "invalid slug" - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is invalid")); - } - - [TestMethod] - public void Validate_WhenSlugIsValid_ReturnsNoValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "valid-slug" - }; - - var result = EventValidator.Validate(event1); - - Assert.IsFalse(result.Any()); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs deleted file mode 100644 index 4d64732a..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs +++ /dev/null @@ -1,62 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class InterestValidatorTests - { - [TestMethod] - public void Validate_WhenNameIsEmpty_ReturnsValidationResult() - { - var interest = new IntrestDto - { - Name = "" - }; - - var result = InterestValidator.Validate(interest); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsTooLong_ReturnsValidationResult() - { - var interest = new IntrestDto - { - Name = new string('a', 33) - }; - - var result = InterestValidator.Validate(interest); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); - } - - [TestMethod] - public void Validate_WhenNameIsInvalid_ReturnsValidationResult() - { - var interest = new IntrestDto - { - Name = "Invalid Name" - }; - - var result = InterestValidator.Validate(interest); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsValid_ReturnsNoValidationResult() - { - var interest = new IntrestDto - { - Name = "Valid Name" - }; - - var result = InterestValidator.Validate(interest); - - Assert.IsFalse(result.Any()); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs deleted file mode 100644 index 5c1480ee..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs +++ /dev/null @@ -1,75 +0,0 @@ -using ReasnAPI.Models.Database; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class ObjectTypeValidatorTests - { - [TestMethod] - public void Validate_WhenNameIsEmpty_ReturnsValidationResult() - { - var objectType = new ObjectType - { - Name = "" - }; - - var result = ObjectTypeValidator.Validate(objectType); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsTooLong_ReturnsValidationResult() - { - var objectType = new ObjectType - { - Name = new string('a', 33) - }; - - var result = ObjectTypeValidator.Validate(objectType); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); - } - - [TestMethod] - public void Validate_WhenNameIsInvalid_ReturnsValidationResult() - { - var objectType = new ObjectType - { - Name = "Invalid Name" - }; - - var result = ObjectTypeValidator.Validate(objectType); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsEvent_ReturnsNoValidationResult() - { - var objectType = new ObjectType - { - Name = "Event" - }; - - var result = ObjectTypeValidator.Validate(objectType); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenNameIsUser_ReturnsNoValidationResult() - { - var objectType = new ObjectType - { - Name = "User" - }; - - var result = ObjectTypeValidator.Validate(objectType); - - Assert.IsFalse(result.Any()); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs deleted file mode 100644 index 424f987b..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs +++ /dev/null @@ -1,109 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class ParameterValidatorTests - { - [TestMethod] - public void Validate_WhenKeyIsEmpty_ReturnsKeyIsRequired() - { - var parameter = new ParameterDto - { - Key = "", - Value = "value" - }; - - var result = ParameterValidator.Validate(parameter); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is invalid")); - } - - [TestMethod] - public void Validate_WhenKeyIsTooLong_ReturnsKeyIsTooLong() - { - var parameter = new ParameterDto - { - Key = new string('a', 33), - Value = "value" - }; - - var result = ParameterValidator.Validate(parameter); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is too long")); - } - - [TestMethod] - public void Validate_WhenKeyIsInvalid_ReturnsKeyIsInvalid() - { - var parameter = new ParameterDto - { - Key = "Invalid Key", - Value = "value" - }; - - var result = ParameterValidator.Validate(parameter); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is invalid")); - } - - [TestMethod] - public void Validate_WhenValueIsEmpty_ReturnsValueIsRequired() - { - var parameter = new ParameterDto - { - Key = "key", - Value = "" - }; - - var result = ParameterValidator.Validate(parameter); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is invalid")); - } - - [TestMethod] - public void Validate_WhenValueIsTooLong_ReturnsValueIsTooLong() - { - var parameter = new ParameterDto - { - Key = "key", - Value = new string('a', 65) - }; - - var result = ParameterValidator.Validate(parameter); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is too long")); - } - - [TestMethod] - public void Validate_WhenValueIsInvalid_ReturnsValueIsInvalid() - { - var parameter = new ParameterDto - { - Key = "key", - Value = "Invalid Value" - }; - - var result = ParameterValidator.Validate(parameter); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is invalid")); - } - - [TestMethod] - public void Validate_WhenValueAndKeyAreValid_ReturnsNoValidationResult() - { - var parameter = new ParameterDto - { - Key = "key", - Value = "value" - }; - - var result = ParameterValidator.Validate(parameter); - - Assert.IsFalse(result.Any()); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs deleted file mode 100644 index a662254a..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs +++ /dev/null @@ -1,75 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class RoleValidatorTests - { - [TestMethod] - public void Validate_WhenRoleNameIsEmpty_ReturnsValidationResult() - { - var role = new RoleDto - { - Name = "" - }; - - var result = RoleValidator.Validate(role); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Role name is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Role name is invalid")); - } - - [TestMethod] - public void Validate_WhenRoleNameIsInvalid_ReturnsValidationResult() - { - var role = new RoleDto - { - Name = "Invalid Role" - }; - - var result = RoleValidator.Validate(role); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Role name is invalid")); - } - - [TestMethod] - public void Validate_WhenRoleNameIsOrganizer_ReturnsNoValidationResult() - { - var role = new RoleDto - { - Name = "Organizer" - }; - - var result = RoleValidator.Validate(role); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenRoleNameIsAdmin_ReturnsNoValidationResult() - { - var role = new RoleDto - { - Name = "Admin" - }; - - var result = RoleValidator.Validate(role); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenRoleNameIsUser_ReturnsNoValidationResult() - { - var role = new RoleDto - { - Name = "User" - }; - - var result = RoleValidator.Validate(role); - - Assert.IsFalse(result.Any()); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs deleted file mode 100644 index c3438cdf..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs +++ /dev/null @@ -1,101 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class StatusValidatorTests - { - [TestMethod] - public void Validate_WhenNameIsEmpty_ReturnsValidationResult() - { - var status = new StatusDto - { - Name = "" - }; - - var result = StatusValidator.Validate(status); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsInvalid_ReturnsValidationResult() - { - var status = new StatusDto - { - Name = "Invalid Name" - }; - - var result = StatusValidator.Validate(status); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsInterested_ReturnsValidationResult() - { - var status = new StatusDto - { - Name = "Interested" - }; - - var result = StatusValidator.Validate(status); - - Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsParticipating_ReturnsValidationResult() - { - var status = new StatusDto - { - Name = "Participating" - }; - - var result = StatusValidator.Validate(status); - - Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsCompleted_ReturnsValidationResult() - { - var status = new StatusDto - { - Name = "Completed" - }; - - var result = StatusValidator.Validate(status); - - Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsInProgress_ReturnsValidationResult() - { - var status = new StatusDto - { - Name = "In progress" - }; - - var result = StatusValidator.Validate(status); - - Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsWaitingForApproval_ReturnsValidationResult() - { - var status = new StatusDto - { - Name = "Waiting for approval" - }; - - var result = StatusValidator.Validate(status); - - Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs deleted file mode 100644 index 4a935bdd..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs +++ /dev/null @@ -1,62 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class TagValidatorTests - { - [TestMethod] - public void Validate_WhenNameIsEmpty_ReturnsValidationResult() - { - var tag = new TagDto - { - Name = "" - }; - - var result = TagValidator.Validate(tag); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsTooLong_ReturnsValidationResult() - { - var tag = new TagDto - { - Name = new string('a', 65) - }; - - var result = TagValidator.Validate(tag); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); - } - - [TestMethod] - public void Validate_WhenNameIsInvalid_ReturnsValidationResult() - { - var tag = new TagDto - { - Name = "Invalid Name" - }; - - var result = TagValidator.Validate(tag); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsValid_ReturnsValidationResult() - { - var tag = new TagDto - { - Name = "Valid Name" - }; - - var result = TagValidator.Validate(tag); - - Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs deleted file mode 100644 index a5de2ecf..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs +++ /dev/null @@ -1,374 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class UserValidatorTests - { - [TestMethod] - public void Validate_WhenNameIsEmpty_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "", - Surname = "Surname", - Username = "Username", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsTooLong_ReturnsValidationResult() - { - var user = new UserDto - { - Name = new string('a', 65), - Surname = "Surname", - Username = "Username", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); - } - - [TestMethod] - public void Validate_WhenNameIsInvalid_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Invalid Name", - Surname = "Surname", - Username = "Username", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsValid_ReturnsNoValidationResult() - { - var user = new UserDto - { - Name = "Validname", - Surname = "Surname", - Username = "Username", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenSurnameIsEmpty_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "", - Username = "Username", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is invalid")); - } - - [TestMethod] - public void Validate_WhenSurnameIsTooLong_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = new string('a', 65), - Username = "Username", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is too long")); - } - - [TestMethod] - public void Validate_WhenSurnameIsInvalid_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Invalid Surname", - Username = "Username", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is invalid")); - } - - [TestMethod] - public void Validate_WhenSurnameIsValid_ReturnsNoValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Validsurname", - Username = "Username", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenUsernameIsEmpty_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is invalid")); - } - - [TestMethod] - public void Validate_WhenUsernameIsTooLong_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = new string('a', 65), - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is too long")); - } - - [TestMethod] - public void Validate_WhenUsernameIsInvalid_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "Invalid Username", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is invalid")); - } - - [TestMethod] - public void Validate_WhenUsernameIsValid_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "ValidUsername", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenEmailIsEmpty_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "Username", - RoleId = 1, - Email = "", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is invalid")); - } - - [TestMethod] - public void Validate_WhenEmailIsTooLong_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "Username", - RoleId = 1, - Email = new string('a', 256), - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is too long")); - } - - [TestMethod] - public void Validate_WhenEmailIsInvalid_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "Username", - RoleId = 1, - Email = "Invalid Email", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is invalid")); - } - - [TestMethod] - public void Validate_WhenEmailIsValid_ReturnsNoValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "Username", - RoleId = 1, - Email = "valid@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenPhoneIsTooLong_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "Username", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = new string('a', 20) - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Phone is too long")); - } - - [TestMethod] - public void Validate_WhenPhoneIsInvalid_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "Username", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "Invalid Phone" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Phone is invalid")); - } - - [TestMethod] - public void Validate_WhenPhoneIsValid_ReturnsNoValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "Username", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsFalse(result.Any()); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs b/Server/ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs index 00c00ff5..d35c8120 100644 --- a/Server/ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs +++ b/Server/ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs @@ -10,7 +10,7 @@ public class EventDto { public DateTime EndAt { get; set; } public DateTime CreatedAt { get; set; } public DateTime UpdatedAt { get; set; } - public string Slug { get; set; } = null!; + public string? Slug { get; set; } public int StatusId { get; set; } public List? Tags { get; set; } } diff --git a/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj b/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj index a5564cb9..02ce3550 100644 --- a/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj +++ b/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj @@ -23,6 +23,7 @@ + diff --git a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs index e6c9897c..08aa4c60 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.DTOs; +using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class AddressValidator : IValidator + public class AddressValidator : IValidator
{ - public static IEnumerable Validate(AddressDto address) + public static IEnumerable Validate(Address address) { if (string.IsNullOrWhiteSpace(address.City)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(AddressDto address) yield return new ValidationResult("City is too long", [nameof(address.City)]); } - if (!new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{Lu}\\p{Ll}+)*$").IsMatch(address.City)) + if (new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{Lu}\\p{Ll}+)*$").IsMatch(address.City) is false) { yield return new ValidationResult("City is invalid", [nameof(address.City)]); } @@ -33,7 +33,7 @@ public static IEnumerable Validate(AddressDto address) yield return new ValidationResult("Country is too long", [nameof(address.Country)]); } - if (!new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)(\\p{Lu}\\p{Ll}+|i|of|and|the)){0,5}$").IsMatch(address.Country)) + if (new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)(\\p{Lu}\\p{Ll}+|i|of|and|the)){0,5}$").IsMatch(address.Country) is false) { yield return new ValidationResult("Country is invalid", [nameof(address.Country)]); } @@ -48,7 +48,7 @@ public static IEnumerable Validate(AddressDto address) yield return new ValidationResult("Street is too long", [nameof(address.Street)]); } - if (!new Regex("^[\\p{L}\\d]+(?:(\\s)\\p{L}+)*(\\s(?:(\\d+\\p{L}?(/\\d*\\p{L}?)?)))?$").IsMatch(address.Street)) + if (new Regex("^[\\p{L}\\d]+(?:(\\s)\\p{L}+)*(\\s(?:(\\d+\\p{L}?(/\\d*\\p{L}?)?)))?$").IsMatch(address.Street) is false) { yield return new ValidationResult("Street is invalid", [nameof(address.Street)]); } @@ -63,7 +63,7 @@ public static IEnumerable Validate(AddressDto address) yield return new ValidationResult("State is too long", [nameof(address.State)]); } - if (!new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{L}+)*$").IsMatch(address.State)) + if (new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{L}+)*$").IsMatch(address.State) is false) { yield return new ValidationResult("State is invalid", [nameof(address.State)]); } @@ -75,7 +75,7 @@ public static IEnumerable Validate(AddressDto address) yield return new ValidationResult("ZipCode is too long", [nameof(address.ZipCode)]); } - if (!new Regex("^[\\p{L}\\d\\s-]{3,}$").IsMatch(address.ZipCode)) + if (new Regex("^[\\p{L}\\d\\s-]{3,}$").IsMatch(address.ZipCode) is false) { yield return new ValidationResult("ZipCode is invalid", [nameof(address.ZipCode)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs index 54a68c45..e4fd2264 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs @@ -1,12 +1,18 @@ -using ReasnAPI.Models.DTOs; +using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; +using System.Numerics; namespace ReasnAPI.Validators { - public class CommentValidator : IValidator + public class CommentValidator : IValidator { - public static IEnumerable Validate(CommentDto comment) + public static IEnumerable Validate(Comment comment) { + if (string.IsNullOrWhiteSpace(comment.EventId.ToString())) + { + yield return new ValidationResult("EventId is required", [nameof(comment.EventId)]); + } + if (string.IsNullOrWhiteSpace(comment.Content)) { yield return new ValidationResult("Content is required", [nameof(comment.Content)]); @@ -17,10 +23,20 @@ public static IEnumerable Validate(CommentDto comment) yield return new ValidationResult("Content is too long", [nameof(comment.Content)]); } - if (comment.CreatedAt >= DateTime.Now) + if (string.IsNullOrWhiteSpace(comment.CreatedAt.ToString())) + { + yield return new ValidationResult("CreatedAt is required", [nameof(comment.CreatedAt)]); + } + + if (comment.CreatedAt > DateTime.Now) { yield return new ValidationResult("CreatedAt is in the future", [nameof(comment.CreatedAt)]); } + + if (string.IsNullOrWhiteSpace(comment.UserId.ToString())) + { + yield return new ValidationResult("UserId is required", [nameof(comment.UserId)]); + } } } } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs index f86f601c..87de07e9 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.DTOs; +using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class EventValidator : IValidator + public class EventValidator : IValidator { - public static IEnumerable Validate(EventDto eventData) + public static IEnumerable Validate(Event eventData) { if (string.IsNullOrWhiteSpace(eventData.Name)) { @@ -18,6 +18,11 @@ public static IEnumerable Validate(EventDto eventData) yield return new ValidationResult("Name is too long", [nameof(eventData.Name)]); } + if (string.IsNullOrWhiteSpace(eventData.AddressId.ToString())) + { + yield return new ValidationResult("AddressId is required", [nameof(eventData.AddressId)]); + } + if (string.IsNullOrWhiteSpace(eventData.Description)) { yield return new ValidationResult("Description is required", [nameof(eventData.Description)]); @@ -28,19 +33,34 @@ public static IEnumerable Validate(EventDto eventData) yield return new ValidationResult("Description is too long", [nameof(eventData.Description)]); } + if (string.IsNullOrWhiteSpace(eventData.OrganizerId.ToString())) + { + yield return new ValidationResult("OrganizerId is required", [nameof(eventData.OrganizerId)]); + } + + if (string.IsNullOrWhiteSpace(eventData.StartAt.ToString())) + { + yield return new ValidationResult("StartTime is required", [nameof(eventData.StartAt)]); + } + + if (string.IsNullOrWhiteSpace(eventData.EndAt.ToString())) + { + yield return new ValidationResult("EndTime is required", [nameof(eventData.EndAt)]); + } + if (eventData.StartAt > eventData.EndAt) { yield return new ValidationResult("StartTime is after EndTime", [nameof(eventData.StartAt)]); } - if (eventData.CreatedAt >= DateTime.Now) + if (string.IsNullOrWhiteSpace(eventData.CreatedAt.ToString())) { - yield return new ValidationResult("CreatedAt is in the future", [nameof(eventData.CreatedAt)]); + yield return new ValidationResult("CreatedAt is required", [nameof(eventData.CreatedAt)]); } - if (eventData.UpdatedAt >= DateTime.Now) + if (string.IsNullOrWhiteSpace(eventData.UpdatedAt.ToString())) { - yield return new ValidationResult("UpdatedAt is in the future", [nameof(eventData.UpdatedAt)]); + yield return new ValidationResult("UpdatedAt is required", [nameof(eventData.UpdatedAt)]); } if (string.IsNullOrWhiteSpace(eventData.Slug)) @@ -53,10 +73,15 @@ public static IEnumerable Validate(EventDto eventData) yield return new ValidationResult("Slug is too long", [nameof(eventData.Slug)]); } - if (!new Regex("^[\\p{L}\\d]+[\\p{L}\\d-]*$").IsMatch(eventData.Slug)) + if (new Regex("^[\\p{L}\\d]+[\\p{L}\\d-]*$").IsMatch(eventData.Slug)) { yield return new ValidationResult("Slug is invalid", [nameof(eventData.Name)]); } + + if (string.IsNullOrWhiteSpace(eventData.StatusId.ToString())) + { + yield return new ValidationResult("StatusId is required", [nameof(eventData.StatusId)]); + } } } } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs new file mode 100644 index 00000000..15de2bfc --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs @@ -0,0 +1,21 @@ +using ReasnAPI.Models.Database; +using System.ComponentModel.DataAnnotations; + +namespace ReasnAPI.Validators +{ + public class ImageValidator : IValidator + { + public static IEnumerable Validate(Image image) + { + if (string.IsNullOrWhiteSpace(image.ObjectTypeId.ToString())) + { + yield return new ValidationResult("ObjectTypeId is required", [nameof(image.ObjectTypeId)]); + } + + if (string.IsNullOrWhiteSpace(image.ObjectId.ToString())) + { + yield return new ValidationResult("ObjectId is required", [nameof(image.ObjectId)]); + } + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs index d6068f0b..ce4704ed 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.DTOs; +using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class InterestValidator : IValidator + public class InterestValidator : IValidator { - public static IEnumerable Validate(IntrestDto interest) + public static IEnumerable Validate(Interest interest) { if (string.IsNullOrWhiteSpace(interest.Name)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(IntrestDto interest) yield return new ValidationResult("Name is too long", [nameof(interest.Name)]); } - if (!new Regex("^\\p{Lu}\\p{Ll}+(?:\\s\\p{L}+)*$").IsMatch(interest.Name)) + if (new Regex("^\\p{Lu}\\p{Ll}+(?:\\s\\p{L}+)*$").IsMatch(interest.Name)) { yield return new ValidationResult("Name is invalid", [nameof(interest.Name)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs index e2e965ce..c26bddaf 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs @@ -18,7 +18,7 @@ public static IEnumerable Validate(ObjectType objectType) yield return new ValidationResult("Name is too long", [nameof(objectType.Name)]); } - if (!new Regex("^(Event|User)$").IsMatch(objectType.Name)) + if (new Regex("^(Event|User)$").IsMatch(objectType.Name) is false) { yield return new ValidationResult("Name is invalid", [nameof(objectType.Name)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs index 42ad28fa..8a06fe21 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.DTOs; +using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class ParameterValidator : IValidator + public class ParameterValidator : IValidator { - public static IEnumerable Validate(ParameterDto parameter) + public static IEnumerable Validate(Parameter parameter) { if (string.IsNullOrWhiteSpace(parameter.Key)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(ParameterDto parameter) yield return new ValidationResult("Key is too long", [nameof(parameter.Key)]); } - if (!new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(parameter.Key)) + if (new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(parameter.Key)) { yield return new ValidationResult("Key is invalid", [nameof(parameter.Key)]); } @@ -33,7 +33,7 @@ public static IEnumerable Validate(ParameterDto parameter) yield return new ValidationResult("Value is too long", [nameof(parameter.Value)]); } - if (!new Regex("^[\\p{L}\\d]+(?:\\s[\\p{L}\\d]+)*$").IsMatch(parameter.Value)) + if (new Regex("^[\\p{L}\\d]+(?:\\s[\\p{L}\\d]+)*$").IsMatch(parameter.Value)) { yield return new ValidationResult("Value is invalid", [nameof(parameter.Value)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs index 83712151..362a9fc9 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs @@ -1,19 +1,24 @@ -using ReasnAPI.Models.DTOs; +using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class RoleValidator : IValidator + public class RoleValidator : IValidator { - public static IEnumerable Validate(RoleDto role) + public static IEnumerable Validate(Role role) { if (string.IsNullOrWhiteSpace(role.Name)) { yield return new ValidationResult("Role name is required", [nameof(role.Name)]); } - if (!new Regex("^(Organizer|Admin|User)$").IsMatch(role.Name)) + if (role.Name.Length > 32) + { + yield return new ValidationResult("Role name is too long", [nameof(role.Name)]); + } + + if (new Regex("^(Organizer|Admin|User)$").IsMatch(role.Name) is false) { yield return new ValidationResult("Role name is invalid", [nameof(role.Name)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs index 680a6e0d..a28e7bb1 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs @@ -1,19 +1,29 @@ -using ReasnAPI.Models.DTOs; +using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class StatusValidator : IValidator + public class StatusValidator : IValidator { - public static IEnumerable Validate(StatusDto status) + public static IEnumerable Validate(Status status) { if (string.IsNullOrWhiteSpace(status.Name)) { yield return new ValidationResult("Name is required", [nameof(status.Name)]); } - if (!new Regex("^(Interested|Participating|Completed|In progress|Waiting for approval)$").IsMatch(status.Name)) + if (status.Name.Length > 32) + { + yield return new ValidationResult("Name is too long", [nameof(status.Name)]); + } + + if (string.IsNullOrWhiteSpace(status.ObjectTypeId.ToString())) + { + yield return new ValidationResult("ObjectTypeId is required", [nameof(status.ObjectTypeId)]); + } + + if (new Regex("^(Interested|Participating|Completed|In progress|Waiting for approval)$").IsMatch(status.Name) is false) { yield return new ValidationResult("Name is invalid", [nameof(status.Name)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs index 10c45944..ff7ee67c 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.DTOs; +using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class TagValidator : IValidator + public class TagValidator : IValidator { - public static IEnumerable Validate(TagDto tag) + public static IEnumerable Validate(Tag tag) { if (string.IsNullOrWhiteSpace(tag.Name)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(TagDto tag) yield return new ValidationResult("Name is too long", [nameof(tag.Name)]); } - if (!new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(tag.Name)) + if (new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(tag.Name)) { yield return new ValidationResult("Name is invalid", [nameof(tag.Name)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs index 2e153655..b6dfb0d0 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.DTOs; +using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class UserValidator : IValidator + public class UserValidator : IValidator { - public static IEnumerable Validate(UserDto user) + public static IEnumerable Validate(User user) { if (string.IsNullOrWhiteSpace(user.Name)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(UserDto user) yield return new ValidationResult("Name is too long", [nameof(user.Name)]); } - if (!new Regex("^\\p{Lu}\\p{Ll}+$").IsMatch(user.Name)) + if (new Regex("^\\p{Lu}\\p{Ll}+$").IsMatch(user.Name) is false) { yield return new ValidationResult("Name is invalid", [nameof(user.Name)]); } @@ -33,7 +33,7 @@ public static IEnumerable Validate(UserDto user) yield return new ValidationResult("Surname is too long", [nameof(user.Surname)]); } - if (!new Regex("^\\p{L}+(?:[\\s'-]?\\p{L}+)*$").IsMatch(user.Surname)) + if (new Regex("^\\p{L}+(?:[\\s'-]?\\p{L}+)*$").IsMatch(user.Surname) is false) { yield return new ValidationResult("Surname is invalid", [nameof(user.Surname)]); } @@ -48,11 +48,31 @@ public static IEnumerable Validate(UserDto user) yield return new ValidationResult("Username is too long", [nameof(user.Username)]); } - if (!new Regex("^[\\p{L}\\d._%+-]+$").IsMatch(user.Username)) + if (new Regex("^[\\p{L}\\d._%+-]+$").IsMatch(user.Username) is false) { yield return new ValidationResult("Username is invalid", [nameof(user.Username)]); } + if (string.IsNullOrWhiteSpace(user.Password)) + { + yield return new ValidationResult("Password is required", [nameof(user.Password)]); + } + + if (string.IsNullOrWhiteSpace(user.CreatedAt.ToString())) + { + yield return new ValidationResult("CreatedAt is required", [nameof(user.CreatedAt)]); + } + + if (string.IsNullOrWhiteSpace(user.UpdatedAt.ToString())) + { + yield return new ValidationResult("UpdatedAt is required", [nameof(user.UpdatedAt)]); + } + + if (string.IsNullOrWhiteSpace(user.RoleId.ToString())) + { + yield return new ValidationResult("RoleId is required", [nameof(user.RoleId)]); + } + if (string.IsNullOrWhiteSpace(user.Email)) { yield return new ValidationResult("Email is required", [nameof(user.Email)]); @@ -63,19 +83,24 @@ public static IEnumerable Validate(UserDto user) yield return new ValidationResult("Email is too long", [nameof(user.Email)]); } - if (!new Regex("^[a-zA-Z\\d._%+-]+@[a-zA-Z\\d.-]+\\.[a-zA-Z]{2,6}$").IsMatch(user.Email)) + if (new Regex("^[a-zA-Z\\d._%+-]+@[a-zA-Z\\d.-]+\\.[a-zA-Z]{2,6}$").IsMatch(user.Email) is false) { yield return new ValidationResult("Email is invalid", [nameof(user.Email)]); } + if (string.IsNullOrWhiteSpace(user.AddressId.ToString())) + { + yield return new ValidationResult("AddressId is required", [nameof(user.AddressId)]); + } + if (!string.IsNullOrWhiteSpace(user.Phone)) { - if (user.Phone.Length > 16) + if (!string.IsNullOrWhiteSpace(user.Phone) && user.Phone.Length > 16) { yield return new ValidationResult("Phone is too long", [nameof(user.Phone)]); } - if (!new Regex("^\\+\\d{1,3}\\s\\d{1,15}$").IsMatch(user.Phone)) + if (new Regex("^\\+\\d{1,3}\\s\\d{1,15}$").IsMatch(user.Phone) is false) { yield return new ValidationResult("Phone is invalid", [nameof(user.Phone)]); } From 444e194e6aebe2193e9ced4f1f067ac42da64896 Mon Sep 17 00:00:00 2001 From: Maciej Koperdowski Date: Mon, 13 May 2024 20:46:33 +0200 Subject: [PATCH 05/24] Added tests, changed models in validators into dtos --- .../ReasnAPI.Tests/ReasnAPI.Tests.csproj | 4 + Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs | 12 - .../Validators/AddressValidatorTests.cs | 336 ++++++++++++++++ .../Validators/CommentValidatorTests.cs | 65 +++ .../Validators/EventValidatorTests.cs | 257 ++++++++++++ .../Validators/InterestValidatorTests.cs | 62 +++ .../Validators/ObjectTypeValidatorTests.cs | 62 +++ .../Validators/ParameterValidatorTests.cs | 109 +++++ .../Validators/RoleValidatorTests.cs | 75 ++++ .../Validators/StatusValidatorTests.cs | 101 +++++ .../Validators/TagValidatorTests.cs | 62 +++ .../Validators/UserValidatorTests.cs | 374 ++++++++++++++++++ .../ReasnAPI/Validators/AddressValidator.cs | 18 +- .../ReasnAPI/Validators/CommentValidator.cs | 26 +- .../ReasnAPI/Validators/EventValidator.cs | 43 +- .../ReasnAPI/Validators/ImageValidator.cs | 21 - .../ReasnAPI/Validators/InterestValidator.cs | 10 +- .../Validators/ObjectTypeValidator.cs | 9 +- .../ReasnAPI/Validators/ParameterValidator.cs | 12 +- .../ReasnAPI/Validators/RoleValidator.cs | 15 +- .../ReasnAPI/Validators/StatusValidator.cs | 20 +- .../ReasnAPI/Validators/TagValidator.cs | 10 +- .../ReasnAPI/Validators/UserValidator.cs | 45 +-- 23 files changed, 1568 insertions(+), 180 deletions(-) delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/AddressValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs diff --git a/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj b/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj index 1b46a3ed..44463a72 100644 --- a/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj +++ b/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj @@ -17,6 +17,10 @@ + + + + diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs deleted file mode 100644 index 46dac6f2..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace ReasnAPI.Tests -{ - [TestClass] - public class UnitTest1 - { - [TestMethod] - public void TestAdd() - { - Assert.AreEqual(17, 17); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/AddressValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/AddressValidatorTests.cs new file mode 100644 index 00000000..c3606a75 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/AddressValidatorTests.cs @@ -0,0 +1,336 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class AddressValidatorTests + { + [TestMethod] + public void Validate_WhenCityIsEmpty_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "", + Country = "Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "City is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "City is invalid")); + } + + [TestMethod] + public void Validate_WhenCityIsTooLong_ReturnsValidationResult() + { + var address = new AddressDto + { + City = new string('a', 65), + Country = "Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "City is too long")); + } + + [TestMethod] + public void Validate_WhenCityIsInvalid_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "Invalid City", + Country = "Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "City is invalid")); + } + + [TestMethod] + public void Validate_WhenCityIsValid_ReturnsNoValidationResult() + { + var address = new AddressDto + { + City = "Valid City", + Country = "Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenCountryIsEmpty_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Country is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Country is invalid")); + } + + [TestMethod] + public void Validate_WhenCountryIsTooLong_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = new string('a', 65), + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Country is too long")); + } + + [TestMethod] + public void Validate_WhenCountryIsInvalid_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Invalid Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Country is invalid")); + } + + [TestMethod] + public void Validate_WhenCountryIsValid_ReturnsNoValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Valid Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenStreetIsEmpty_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Street is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Street is invalid")); + } + + [TestMethod] + public void Validate_WhenStreetIsTooLong_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = new string('a', 65), + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Street is too long")); + } + + [TestMethod] + public void Validate_WhenStreetIsInvalid_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Invalid Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Street is invalid")); + } + + [TestMethod] + public void Validate_WhenStreetIsValid_ReturnsNoValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Valid Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenStateIsEmpty_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = "", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "State is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "State is invalid")); + } + + [TestMethod] + public void Validate_WhenStateIsTooLong_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = new string('a', 65), + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "State is too long")); + } + + [TestMethod] + public void Validate_WhenStateIsInvalid_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = "Invalid State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "State is invalid")); + } + + [TestMethod] + public void Validate_WhenStateIsValid_ReturnsNoValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = "Valid State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Valdate_WhenZipCodeIsTooLong_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = "State", + ZipCode = new string('0', 9) + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "ZipCode is too long")); + } + + [TestMethod] + public void Validate_WhenZipCodeIsInvalid_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = "State", + ZipCode = "Invalid_" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "ZipCode is invalid")); + } + + [TestMethod] + public void Validate_WhenZipCodeIsValid_ReturnsNoValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsFalse(result.Any()); + } + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs new file mode 100644 index 00000000..2f714be0 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs @@ -0,0 +1,65 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class CommentValidatorTests + { + [TestMethod] + public void Validate_WhenContentIsEmpty_ReturnsValidationResult() + { + var comment = new CommentDto + { + Content = "", + CreatedAt = DateTime.Now + }; + + var result = CommentValidator.Validate(comment); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Content is required")); + } + + [TestMethod] + public void Validate_WhenContentIsTooLong_ReturnsValidationResult() + { + var comment = new CommentDto + { + Content = new string('a', 1025), + CreatedAt = DateTime.Now + }; + + var result = CommentValidator.Validate(comment); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Content is too long")); + } + + [TestMethod] + public void Validate_WhenCreatedAtIsInTheFuture_ReturnsValidationResult() + { + var comment = new CommentDto + { + Content = "Content", + CreatedAt = DateTime.Now.AddMinutes(1) + }; + + var result = CommentValidator.Validate(comment); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "CreatedAt is in the future")); + } + + [TestMethod] + public void Validate_WhenCommentIsValid_ReturnsNoValidationResult() + { + var comment = new CommentDto + { + Content = "Content", + CreatedAt = DateTime.Now + }; + + var result = CommentValidator.Validate(comment); + + Assert.IsFalse(result.Any()); + } + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs new file mode 100644 index 00000000..384b52ab --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs @@ -0,0 +1,257 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class EventValidatorTests + { + [TestMethod] + public void Validate_WhenNameIsEmpty_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); + } + + [TestMethod] + public void Validate_WhenNameIsTooLong_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = new string('a', 65), + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); + } + + [TestMethod] + public void Validate_WhenNameIsValid_ReturnsNoValidationResult() + { + var event1 = new EventDto + { + Name = "ValidName", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenDescriptionIsEmpty_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Description is required")); + } + + [TestMethod] + public void Validate_WhenDescriptionIsTooLong_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = new string('a', 4049), + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Description is too long")); + } + + [TestMethod] + public void Validate_WhenDescriptionIsValid_ReturnsNoValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Valid Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenStartAtIsAfterEndAt_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now.AddMinutes(1), + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "StartTime is after EndTime")); + } + + [TestMethod] + public void Validate_WhenCreatedAtIsInTheFuture_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now.AddMinutes(1), + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "CreatedAt is in the future")); + } + + [TestMethod] + public void Validate_WhenUpdatedAtIsInTheFuture_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now.AddMinutes(1), + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "UpdatedAt is in the future")); + } + + [TestMethod] + public void Validate_WhenSlugIsEmpty_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is invalid")); + } + + [TestMethod] + public void Validate_WhenSlugIsTooLong_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = new string('a', 129) + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is too long")); + } + + [TestMethod] + public void Validate_WhenSlugIsIsInvalid_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "invalid slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is invalid")); + } + + [TestMethod] + public void Validate_WhenSlugIsValid_ReturnsNoValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "valid-slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsFalse(result.Any()); + } + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs new file mode 100644 index 00000000..b1a3bd5c --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs @@ -0,0 +1,62 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class InterestValidatorTests + { + [TestMethod] + public void Validate_WhenNameIsEmpty_ReturnsValidationResult() + { + var interest = new IntrestDto + { + Name = "" + }; + + var result = InterestValidator.Validate(interest); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsTooLong_ReturnsValidationResult() + { + var interest = new IntrestDto + { + Name = new string('a', 33) + }; + + var result = InterestValidator.Validate(interest); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); + } + + [TestMethod] + public void Validate_WhenNameIsInvalid_ReturnsValidationResult() + { + var interest = new IntrestDto + { + Name = "Invalid Name" + }; + + var result = InterestValidator.Validate(interest); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsValid_ReturnsNoValidationResult() + { + var interest = new IntrestDto + { + Name = "Valid Name" + }; + + var result = InterestValidator.Validate(interest); + + Assert.IsFalse(result.Any()); + } + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs new file mode 100644 index 00000000..80fb499a --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs @@ -0,0 +1,62 @@ +using ReasnAPI.Models.Database; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class ObjectTypeValidatorTests + { + [TestMethod] + public void Validate_WhenNameIsEmpty_ReturnsValidationResult() + { + var objectType = new ObjectType + { + Name = "" + }; + + var result = ObjectTypeValidator.Validate(objectType); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsInvalid_ReturnsValidationResult() + { + var objectType = new ObjectType + { + Name = "Invalid Name" + }; + + var result = ObjectTypeValidator.Validate(objectType); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsEvent_ReturnsNoValidationResult() + { + var objectType = new ObjectType + { + Name = "Event" + }; + + var result = ObjectTypeValidator.Validate(objectType); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenNameIsUser_ReturnsNoValidationResult() + { + var objectType = new ObjectType + { + Name = "User" + }; + + var result = ObjectTypeValidator.Validate(objectType); + + Assert.IsFalse(result.Any()); + } + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs new file mode 100644 index 00000000..601f69ed --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs @@ -0,0 +1,109 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class ParameterValidatorTests + { + [TestMethod] + public void Validate_WhenKeyIsEmpty_ReturnsKeyIsRequired() + { + var parameter = new ParameterDto + { + Key = "", + Value = "value" + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is invalid")); + } + + [TestMethod] + public void Validate_WhenKeyIsTooLong_ReturnsKeyIsTooLong() + { + var parameter = new ParameterDto + { + Key = new string('a', 33), + Value = "value" + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is too long")); + } + + [TestMethod] + public void Validate_WhenKeyIsInvalid_ReturnsKeyIsInvalid() + { + var parameter = new ParameterDto + { + Key = "Invalid Key", + Value = "value" + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is invalid")); + } + + [TestMethod] + public void Validate_WhenValueIsEmpty_ReturnsValueIsRequired() + { + var parameter = new ParameterDto + { + Key = "key", + Value = "" + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is invalid")); + } + + [TestMethod] + public void Validate_WhenValueIsTooLong_ReturnsValueIsTooLong() + { + var parameter = new ParameterDto + { + Key = "key", + Value = new string('a', 65) + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is too long")); + } + + [TestMethod] + public void Validate_WhenValueIsInvalid_ReturnsValueIsInvalid() + { + var parameter = new ParameterDto + { + Key = "key", + Value = "Invalid Value" + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is invalid")); + } + + [TestMethod] + public void Validate_WhenValueAndKeyAreValid_ReturnsNoValidationResult() + { + var parameter = new ParameterDto + { + Key = "key", + Value = "value" + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsFalse(result.Any()); + } + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs new file mode 100644 index 00000000..0509dbe1 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs @@ -0,0 +1,75 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class RoleValidatorTests + { + [TestMethod] + public void Validate_WhenRoleNameIsEmpty_ReturnsValidationResult() + { + var role = new RoleDto + { + Name = "" + }; + + var result = RoleValidator.Validate(role); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Role name is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Role name is invalid")); + } + + [TestMethod] + public void Validate_WhenRoleNameIsInvalid_ReturnsValidationResult() + { + var role = new RoleDto + { + Name = "Invalid Role" + }; + + var result = RoleValidator.Validate(role); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Role name is invalid")); + } + + [TestMethod] + public void Validate_WhenRoleNameIsOrganizer_ReturnsNoValidationResult() + { + var role = new RoleDto + { + Name = "Organizer" + }; + + var result = RoleValidator.Validate(role); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenRoleNameIsAdmin_ReturnsNoValidationResult() + { + var role = new RoleDto + { + Name = "Admin" + }; + + var result = RoleValidator.Validate(role); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenRoleNameIsUser_ReturnsNoValidationResult() + { + var role = new RoleDto + { + Name = "User" + }; + + var result = RoleValidator.Validate(role); + + Assert.IsFalse(result.Any()); + } + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs new file mode 100644 index 00000000..46a2b05b --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs @@ -0,0 +1,101 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class StatusValidatorTests + { + [TestMethod] + public void Validate_WhenNameIsEmpty_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsInvalid_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "Invalid Name" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsInterested_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "Interested" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsParticipating_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "Participating" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsCompleted_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "Completed" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsInProgress_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "In progress" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsWaitingForApproval_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "Waiting for approval" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs new file mode 100644 index 00000000..98b163b3 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs @@ -0,0 +1,62 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class TagValidatorTests + { + [TestMethod] + public void Validate_WhenNameIsEmpty_ReturnsValidationResult() + { + var tag = new TagDto + { + Name = "" + }; + + var result = TagValidator.Validate(tag); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsTooLong_ReturnsValidationResult() + { + var tag = new TagDto + { + Name = new string('a', 65) + }; + + var result = TagValidator.Validate(tag); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); + } + + [TestMethod] + public void Validate_WhenNameIsInvalid_ReturnsValidationResult() + { + var tag = new TagDto + { + Name = "Invalid Name" + }; + + var result = TagValidator.Validate(tag); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsValid_ReturnsValidationResult() + { + var tag = new TagDto + { + Name = "Valid Name" + }; + + var result = TagValidator.Validate(tag); + + Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs new file mode 100644 index 00000000..47cea2a3 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs @@ -0,0 +1,374 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class UserValidatorTests + { + [TestMethod] + public void Validate_WhenNameIsEmpty_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsTooLong_ReturnsValidationResult() + { + var user = new UserDto + { + Name = new string('a', 65), + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); + } + + [TestMethod] + public void Validate_WhenNameIsInvalid_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Invalid Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsValid_ReturnsNoValidationResult() + { + var user = new UserDto + { + Name = "Validname", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenSurnameIsEmpty_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is invalid")); + } + + [TestMethod] + public void Validate_WhenSurnameIsTooLong_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = new string('a', 65), + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is too long")); + } + + [TestMethod] + public void Validate_WhenSurnameIsInvalid_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Invalid Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is invalid")); + } + + [TestMethod] + public void Validate_WhenSurnameIsValid_ReturnsNoValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Validsurname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenUsernameIsEmpty_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is invalid")); + } + + [TestMethod] + public void Validate_WhenUsernameIsTooLong_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = new string('a', 65), + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is too long")); + } + + [TestMethod] + public void Validate_WhenUsernameIsInvalid_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Invalid Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is invalid")); + } + + [TestMethod] + public void Validate_WhenUsernameIsValid_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "ValidUsername", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenEmailIsEmpty_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is invalid")); + } + + [TestMethod] + public void Validate_WhenEmailIsTooLong_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = new string('a', 256), + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is too long")); + } + + [TestMethod] + public void Validate_WhenEmailIsInvalid_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "Invalid Email", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is invalid")); + } + + [TestMethod] + public void Validate_WhenEmailIsValid_ReturnsNoValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "valid@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenPhoneIsTooLong_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = new string('a', 20) + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Phone is too long")); + } + + [TestMethod] + public void Validate_WhenPhoneIsInvalid_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "Invalid Phone" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Phone is invalid")); + } + + [TestMethod] + public void Validate_WhenPhoneIsValid_ReturnsNoValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsFalse(result.Any()); + } + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs index 08aa4c60..dfad3dc9 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class AddressValidator : IValidator
+ public class AddressValidator : IValidator { - public static IEnumerable Validate(Address address) + public static IEnumerable Validate(AddressDto address) { if (string.IsNullOrWhiteSpace(address.City)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("City is too long", [nameof(address.City)]); } - if (new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{Lu}\\p{Ll}+)*$").IsMatch(address.City) is false) + if (!new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{Lu}\\p{Ll}+)*$").IsMatch(address.City)) { yield return new ValidationResult("City is invalid", [nameof(address.City)]); } @@ -33,7 +33,7 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("Country is too long", [nameof(address.Country)]); } - if (new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)(\\p{Lu}\\p{Ll}+|i|of|and|the)){0,5}$").IsMatch(address.Country) is false) + if (!new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)(\\p{Lu}\\p{Ll}+|i|of|and|the)){0,5}$").IsMatch(address.Country)) { yield return new ValidationResult("Country is invalid", [nameof(address.Country)]); } @@ -48,7 +48,7 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("Street is too long", [nameof(address.Street)]); } - if (new Regex("^[\\p{L}\\d]+(?:(\\s)\\p{L}+)*(\\s(?:(\\d+\\p{L}?(/\\d*\\p{L}?)?)))?$").IsMatch(address.Street) is false) + if (!new Regex("^[\\p{L}\\d]+(?:(\\s)\\p{L}+)*(\\s(?:(\\d+\\p{L}?(/\\d*\\p{L}?)?)))?$").IsMatch(address.Street)) { yield return new ValidationResult("Street is invalid", [nameof(address.Street)]); } @@ -63,7 +63,7 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("State is too long", [nameof(address.State)]); } - if (new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{L}+)*$").IsMatch(address.State) is false) + if (!new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{L}+)*$").IsMatch(address.State)) { yield return new ValidationResult("State is invalid", [nameof(address.State)]); } @@ -75,11 +75,11 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("ZipCode is too long", [nameof(address.ZipCode)]); } - if (new Regex("^[\\p{L}\\d\\s-]{3,}$").IsMatch(address.ZipCode) is false) + if (!new Regex("^[\\p{L}\\d\\s-]{3,}$").IsMatch(address.ZipCode)) { yield return new ValidationResult("ZipCode is invalid", [nameof(address.ZipCode)]); } } } } -} +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs index e4fd2264..ea80de6c 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs @@ -1,18 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; -using System.Numerics; namespace ReasnAPI.Validators { - public class CommentValidator : IValidator + public class CommentValidator : IValidator { - public static IEnumerable Validate(Comment comment) + public static IEnumerable Validate(CommentDto comment) { - if (string.IsNullOrWhiteSpace(comment.EventId.ToString())) - { - yield return new ValidationResult("EventId is required", [nameof(comment.EventId)]); - } - if (string.IsNullOrWhiteSpace(comment.Content)) { yield return new ValidationResult("Content is required", [nameof(comment.Content)]); @@ -23,20 +17,10 @@ public static IEnumerable Validate(Comment comment) yield return new ValidationResult("Content is too long", [nameof(comment.Content)]); } - if (string.IsNullOrWhiteSpace(comment.CreatedAt.ToString())) - { - yield return new ValidationResult("CreatedAt is required", [nameof(comment.CreatedAt)]); - } - - if (comment.CreatedAt > DateTime.Now) + if (comment.CreatedAt >= DateTime.Now) { yield return new ValidationResult("CreatedAt is in the future", [nameof(comment.CreatedAt)]); } - - if (string.IsNullOrWhiteSpace(comment.UserId.ToString())) - { - yield return new ValidationResult("UserId is required", [nameof(comment.UserId)]); - } } } -} +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs index 87de07e9..cd35b64d 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class EventValidator : IValidator + public class EventValidator : IValidator { - public static IEnumerable Validate(Event eventData) + public static IEnumerable Validate(EventDto eventData) { if (string.IsNullOrWhiteSpace(eventData.Name)) { @@ -18,11 +18,6 @@ public static IEnumerable Validate(Event eventData) yield return new ValidationResult("Name is too long", [nameof(eventData.Name)]); } - if (string.IsNullOrWhiteSpace(eventData.AddressId.ToString())) - { - yield return new ValidationResult("AddressId is required", [nameof(eventData.AddressId)]); - } - if (string.IsNullOrWhiteSpace(eventData.Description)) { yield return new ValidationResult("Description is required", [nameof(eventData.Description)]); @@ -33,34 +28,19 @@ public static IEnumerable Validate(Event eventData) yield return new ValidationResult("Description is too long", [nameof(eventData.Description)]); } - if (string.IsNullOrWhiteSpace(eventData.OrganizerId.ToString())) - { - yield return new ValidationResult("OrganizerId is required", [nameof(eventData.OrganizerId)]); - } - - if (string.IsNullOrWhiteSpace(eventData.StartAt.ToString())) - { - yield return new ValidationResult("StartTime is required", [nameof(eventData.StartAt)]); - } - - if (string.IsNullOrWhiteSpace(eventData.EndAt.ToString())) - { - yield return new ValidationResult("EndTime is required", [nameof(eventData.EndAt)]); - } - if (eventData.StartAt > eventData.EndAt) { yield return new ValidationResult("StartTime is after EndTime", [nameof(eventData.StartAt)]); } - if (string.IsNullOrWhiteSpace(eventData.CreatedAt.ToString())) + if (eventData.CreatedAt >= DateTime.Now) { - yield return new ValidationResult("CreatedAt is required", [nameof(eventData.CreatedAt)]); + yield return new ValidationResult("CreatedAt is in the future", [nameof(eventData.CreatedAt)]); } - if (string.IsNullOrWhiteSpace(eventData.UpdatedAt.ToString())) + if (eventData.UpdatedAt >= DateTime.Now) { - yield return new ValidationResult("UpdatedAt is required", [nameof(eventData.UpdatedAt)]); + yield return new ValidationResult("UpdatedAt is in the future", [nameof(eventData.UpdatedAt)]); } if (string.IsNullOrWhiteSpace(eventData.Slug)) @@ -73,15 +53,10 @@ public static IEnumerable Validate(Event eventData) yield return new ValidationResult("Slug is too long", [nameof(eventData.Slug)]); } - if (new Regex("^[\\p{L}\\d]+[\\p{L}\\d-]*$").IsMatch(eventData.Slug)) + if (!new Regex("^[\\p{L}\\d]+[\\p{L}\\d-]*$").IsMatch(eventData.Slug)) { yield return new ValidationResult("Slug is invalid", [nameof(eventData.Name)]); } - - if (string.IsNullOrWhiteSpace(eventData.StatusId.ToString())) - { - yield return new ValidationResult("StatusId is required", [nameof(eventData.StatusId)]); - } } } -} +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs deleted file mode 100644 index 15de2bfc..00000000 --- a/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs +++ /dev/null @@ -1,21 +0,0 @@ -using ReasnAPI.Models.Database; -using System.ComponentModel.DataAnnotations; - -namespace ReasnAPI.Validators -{ - public class ImageValidator : IValidator - { - public static IEnumerable Validate(Image image) - { - if (string.IsNullOrWhiteSpace(image.ObjectTypeId.ToString())) - { - yield return new ValidationResult("ObjectTypeId is required", [nameof(image.ObjectTypeId)]); - } - - if (string.IsNullOrWhiteSpace(image.ObjectId.ToString())) - { - yield return new ValidationResult("ObjectId is required", [nameof(image.ObjectId)]); - } - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs index ce4704ed..d65fc8fb 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class InterestValidator : IValidator + public class InterestValidator : IValidator { - public static IEnumerable Validate(Interest interest) + public static IEnumerable Validate(IntrestDto interest) { if (string.IsNullOrWhiteSpace(interest.Name)) { @@ -18,10 +18,10 @@ public static IEnumerable Validate(Interest interest) yield return new ValidationResult("Name is too long", [nameof(interest.Name)]); } - if (new Regex("^\\p{Lu}\\p{Ll}+(?:\\s\\p{L}+)*$").IsMatch(interest.Name)) + if (!new Regex("^\\p{Lu}\\p{Ll}+(?:\\s\\p{L}+)*$").IsMatch(interest.Name)) { yield return new ValidationResult("Name is invalid", [nameof(interest.Name)]); } } } -} +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs index c26bddaf..af303d50 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs @@ -13,15 +13,10 @@ public static IEnumerable Validate(ObjectType objectType) yield return new ValidationResult("Name is required", [nameof(objectType.Name)]); } - if (objectType.Name.Length > 32) - { - yield return new ValidationResult("Name is too long", [nameof(objectType.Name)]); - } - - if (new Regex("^(Event|User)$").IsMatch(objectType.Name) is false) + if (!new Regex("^(Event|User)$").IsMatch(objectType.Name)) { yield return new ValidationResult("Name is invalid", [nameof(objectType.Name)]); } } } -} +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs index 8a06fe21..c4e64206 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class ParameterValidator : IValidator + public class ParameterValidator : IValidator { - public static IEnumerable Validate(Parameter parameter) + public static IEnumerable Validate(ParameterDto parameter) { if (string.IsNullOrWhiteSpace(parameter.Key)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(Parameter parameter) yield return new ValidationResult("Key is too long", [nameof(parameter.Key)]); } - if (new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(parameter.Key)) + if (!new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(parameter.Key)) { yield return new ValidationResult("Key is invalid", [nameof(parameter.Key)]); } @@ -33,10 +33,10 @@ public static IEnumerable Validate(Parameter parameter) yield return new ValidationResult("Value is too long", [nameof(parameter.Value)]); } - if (new Regex("^[\\p{L}\\d]+(?:\\s[\\p{L}\\d]+)*$").IsMatch(parameter.Value)) + if (!new Regex("^[\\p{L}\\d]+(?:\\s[\\p{L}\\d]+)*$").IsMatch(parameter.Value)) { yield return new ValidationResult("Value is invalid", [nameof(parameter.Value)]); } } } -} +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs index 362a9fc9..90598e29 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs @@ -1,27 +1,22 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class RoleValidator : IValidator + public class RoleValidator : IValidator { - public static IEnumerable Validate(Role role) + public static IEnumerable Validate(RoleDto role) { if (string.IsNullOrWhiteSpace(role.Name)) { yield return new ValidationResult("Role name is required", [nameof(role.Name)]); } - if (role.Name.Length > 32) - { - yield return new ValidationResult("Role name is too long", [nameof(role.Name)]); - } - - if (new Regex("^(Organizer|Admin|User)$").IsMatch(role.Name) is false) + if (!new Regex("^(Organizer|Admin|User)$").IsMatch(role.Name)) { yield return new ValidationResult("Role name is invalid", [nameof(role.Name)]); } } } -} +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs index a28e7bb1..4ec34e93 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs @@ -1,32 +1,22 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class StatusValidator : IValidator + public class StatusValidator : IValidator { - public static IEnumerable Validate(Status status) + public static IEnumerable Validate(StatusDto status) { if (string.IsNullOrWhiteSpace(status.Name)) { yield return new ValidationResult("Name is required", [nameof(status.Name)]); } - if (status.Name.Length > 32) - { - yield return new ValidationResult("Name is too long", [nameof(status.Name)]); - } - - if (string.IsNullOrWhiteSpace(status.ObjectTypeId.ToString())) - { - yield return new ValidationResult("ObjectTypeId is required", [nameof(status.ObjectTypeId)]); - } - - if (new Regex("^(Interested|Participating|Completed|In progress|Waiting for approval)$").IsMatch(status.Name) is false) + if (!new Regex("^(Interested|Participating|Completed|In progress|Waiting for approval)$").IsMatch(status.Name)) { yield return new ValidationResult("Name is invalid", [nameof(status.Name)]); } } } -} +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs index ff7ee67c..f871c817 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class TagValidator : IValidator + public class TagValidator : IValidator { - public static IEnumerable Validate(Tag tag) + public static IEnumerable Validate(TagDto tag) { if (string.IsNullOrWhiteSpace(tag.Name)) { @@ -18,10 +18,10 @@ public static IEnumerable Validate(Tag tag) yield return new ValidationResult("Name is too long", [nameof(tag.Name)]); } - if (new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(tag.Name)) + if (!new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(tag.Name)) { yield return new ValidationResult("Name is invalid", [nameof(tag.Name)]); } } } -} +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs index b6dfb0d0..77602102 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class UserValidator : IValidator + public class UserValidator : IValidator { - public static IEnumerable Validate(User user) + public static IEnumerable Validate(UserDto user) { if (string.IsNullOrWhiteSpace(user.Name)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(User user) yield return new ValidationResult("Name is too long", [nameof(user.Name)]); } - if (new Regex("^\\p{Lu}\\p{Ll}+$").IsMatch(user.Name) is false) + if (!new Regex("^\\p{Lu}\\p{Ll}+$").IsMatch(user.Name)) { yield return new ValidationResult("Name is invalid", [nameof(user.Name)]); } @@ -33,7 +33,7 @@ public static IEnumerable Validate(User user) yield return new ValidationResult("Surname is too long", [nameof(user.Surname)]); } - if (new Regex("^\\p{L}+(?:[\\s'-]?\\p{L}+)*$").IsMatch(user.Surname) is false) + if (!new Regex("^\\p{L}+(?:[\\s'-]?\\p{L}+)*$").IsMatch(user.Surname)) { yield return new ValidationResult("Surname is invalid", [nameof(user.Surname)]); } @@ -48,31 +48,11 @@ public static IEnumerable Validate(User user) yield return new ValidationResult("Username is too long", [nameof(user.Username)]); } - if (new Regex("^[\\p{L}\\d._%+-]+$").IsMatch(user.Username) is false) + if (!new Regex("^[\\p{L}\\d._%+-]+$").IsMatch(user.Username)) { yield return new ValidationResult("Username is invalid", [nameof(user.Username)]); } - if (string.IsNullOrWhiteSpace(user.Password)) - { - yield return new ValidationResult("Password is required", [nameof(user.Password)]); - } - - if (string.IsNullOrWhiteSpace(user.CreatedAt.ToString())) - { - yield return new ValidationResult("CreatedAt is required", [nameof(user.CreatedAt)]); - } - - if (string.IsNullOrWhiteSpace(user.UpdatedAt.ToString())) - { - yield return new ValidationResult("UpdatedAt is required", [nameof(user.UpdatedAt)]); - } - - if (string.IsNullOrWhiteSpace(user.RoleId.ToString())) - { - yield return new ValidationResult("RoleId is required", [nameof(user.RoleId)]); - } - if (string.IsNullOrWhiteSpace(user.Email)) { yield return new ValidationResult("Email is required", [nameof(user.Email)]); @@ -83,24 +63,19 @@ public static IEnumerable Validate(User user) yield return new ValidationResult("Email is too long", [nameof(user.Email)]); } - if (new Regex("^[a-zA-Z\\d._%+-]+@[a-zA-Z\\d.-]+\\.[a-zA-Z]{2,6}$").IsMatch(user.Email) is false) + if (!new Regex("^[a-zA-Z\\d._%+-]+@[a-zA-Z\\d.-]+\\.[a-zA-Z]{2,6}$").IsMatch(user.Email)) { yield return new ValidationResult("Email is invalid", [nameof(user.Email)]); } - if (string.IsNullOrWhiteSpace(user.AddressId.ToString())) - { - yield return new ValidationResult("AddressId is required", [nameof(user.AddressId)]); - } - if (!string.IsNullOrWhiteSpace(user.Phone)) { - if (!string.IsNullOrWhiteSpace(user.Phone) && user.Phone.Length > 16) + if (user.Phone.Length > 16) { yield return new ValidationResult("Phone is too long", [nameof(user.Phone)]); } - if (new Regex("^\\+\\d{1,3}\\s\\d{1,15}$").IsMatch(user.Phone) is false) + if (!new Regex("^\\+\\d{1,3}\\s\\d{1,15}$").IsMatch(user.Phone)) { yield return new ValidationResult("Phone is invalid", [nameof(user.Phone)]); } @@ -108,4 +83,4 @@ public static IEnumerable Validate(User user) } } -} +} \ No newline at end of file From a3370261bc4b90f88642c6c1b81c36d2f87a502a Mon Sep 17 00:00:00 2001 From: Maciej Koperdowski Date: Mon, 13 May 2024 21:00:39 +0200 Subject: [PATCH 06/24] Deleted EventDto changes --- Server/ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs b/Server/ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs index d35c8120..00c00ff5 100644 --- a/Server/ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs +++ b/Server/ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs @@ -10,7 +10,7 @@ public class EventDto { public DateTime EndAt { get; set; } public DateTime CreatedAt { get; set; } public DateTime UpdatedAt { get; set; } - public string? Slug { get; set; } + public string Slug { get; set; } = null!; public int StatusId { get; set; } public List? Tags { get; set; } } From e794972c37cf03ba90665501c5c7c168091b11bd Mon Sep 17 00:00:00 2001 From: Maciej Koperdowski Date: Mon, 13 May 2024 21:16:38 +0200 Subject: [PATCH 07/24] Unit test fix --- .../Validators/EventValidatorTests.cs | 25 ++++++++++--------- .../ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs | 2 +- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs index 384b52ab..aa4839c9 100644 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs @@ -1,5 +1,6 @@ using ReasnAPI.Models.DTOs; using ReasnAPI.Validators; +using System; namespace ReasnAPI.Tests.Validators { @@ -14,7 +15,7 @@ public void Validate_WhenNameIsEmpty_ReturnsValidationResult() Name = "", Description = "Description", StartAt = DateTime.Now, - EndAt = DateTime.Now, + EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, Slug = "slug" @@ -33,7 +34,7 @@ public void Validate_WhenNameIsTooLong_ReturnsValidationResult() Name = new string('a', 65), Description = "Description", StartAt = DateTime.Now, - EndAt = DateTime.Now, + EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, Slug = "slug" @@ -52,7 +53,7 @@ public void Validate_WhenNameIsValid_ReturnsNoValidationResult() Name = "ValidName", Description = "Description", StartAt = DateTime.Now, - EndAt = DateTime.Now, + EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, Slug = "slug" @@ -71,7 +72,7 @@ public void Validate_WhenDescriptionIsEmpty_ReturnsValidationResult() Name = "Name", Description = "", StartAt = DateTime.Now, - EndAt = DateTime.Now, + EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, Slug = "slug" @@ -90,7 +91,7 @@ public void Validate_WhenDescriptionIsTooLong_ReturnsValidationResult() Name = "Name", Description = new string('a', 4049), StartAt = DateTime.Now, - EndAt = DateTime.Now, + EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, Slug = "slug" @@ -109,7 +110,7 @@ public void Validate_WhenDescriptionIsValid_ReturnsNoValidationResult() Name = "Name", Description = "Valid Description", StartAt = DateTime.Now, - EndAt = DateTime.Now, + EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, Slug = "slug" @@ -147,7 +148,7 @@ public void Validate_WhenCreatedAtIsInTheFuture_ReturnsValidationResult() Name = "Name", Description = "Description", StartAt = DateTime.Now, - EndAt = DateTime.Now, + EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now.AddMinutes(1), UpdatedAt = DateTime.Now, Slug = "slug" @@ -166,7 +167,7 @@ public void Validate_WhenUpdatedAtIsInTheFuture_ReturnsValidationResult() Name = "Name", Description = "Description", StartAt = DateTime.Now, - EndAt = DateTime.Now, + EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now.AddMinutes(1), Slug = "slug" @@ -185,7 +186,7 @@ public void Validate_WhenSlugIsEmpty_ReturnsValidationResult() Name = "Name", Description = "Description", StartAt = DateTime.Now, - EndAt = DateTime.Now, + EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, Slug = "" @@ -205,7 +206,7 @@ public void Validate_WhenSlugIsTooLong_ReturnsValidationResult() Name = "Name", Description = "Description", StartAt = DateTime.Now, - EndAt = DateTime.Now, + EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, Slug = new string('a', 129) @@ -224,7 +225,7 @@ public void Validate_WhenSlugIsIsInvalid_ReturnsValidationResult() Name = "Name", Description = "Description", StartAt = DateTime.Now, - EndAt = DateTime.Now, + EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, Slug = "invalid slug" @@ -243,7 +244,7 @@ public void Validate_WhenSlugIsValid_ReturnsNoValidationResult() Name = "Name", Description = "Description", StartAt = DateTime.Now, - EndAt = DateTime.Now, + EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, Slug = "valid-slug" diff --git a/Server/ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs b/Server/ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs index 00c00ff5..d35c8120 100644 --- a/Server/ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs +++ b/Server/ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs @@ -10,7 +10,7 @@ public class EventDto { public DateTime EndAt { get; set; } public DateTime CreatedAt { get; set; } public DateTime UpdatedAt { get; set; } - public string Slug { get; set; } = null!; + public string? Slug { get; set; } public int StatusId { get; set; } public List? Tags { get; set; } } From c5dcd82367c7a2cd49f55a5e9f0a553e11fb1662 Mon Sep 17 00:00:00 2001 From: Maciej Koperdowski Date: Tue, 14 May 2024 10:39:26 +0200 Subject: [PATCH 08/24] Restore ReasnAPI.csproj --- Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj b/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj index 02ce3550..23499ae8 100644 --- a/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj +++ b/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj @@ -25,6 +25,7 @@ + From be3fc4757d0c13d1428be31036751f10d2aa6484 Mon Sep 17 00:00:00 2001 From: Maciej Koperdowski Date: Wed, 15 May 2024 18:20:23 +0200 Subject: [PATCH 09/24] Created const variables for regex strings and hardcoded numbers --- .../ReasnAPI/Validators/AddressValidator.cs | 31 +++++++++++++------ .../ReasnAPI/Validators/CommentValidator.cs | 4 ++- .../ReasnAPI/Validators/EventValidator.cs | 13 +++++--- .../ReasnAPI/Validators/InterestValidator.cs | 7 +++-- .../ReasnAPI/Validators/ParameterValidator.cs | 13 +++++--- .../ReasnAPI/Validators/TagValidator.cs | 7 +++-- 6 files changed, 52 insertions(+), 23 deletions(-) diff --git a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs index dfad3dc9..6a7b5214 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs @@ -6,6 +6,17 @@ namespace ReasnAPI.Validators { public class AddressValidator : IValidator { + private const int CityMaxLength = 64; + private const string CityRegexPattern = "^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{Lu}\\p{Ll}+)*$"; + private const int CountryMaxLength = 64; + private const string CountryRegexPattern = "^\\p{Lu}\\p{Ll}+(?:(\\s|-)(\\p{Lu}\\p{Ll}+|i|of|and|the)){0,5}$"; + private const int StreetMaxLength = 64; + private const string StreetRegexPattern = "^[\\p{L}\\d]+(?:(\\s)\\p{L}+)*(\\s(?:(\\d+\\p{L}?(/\\d*\\p{L}?)?)))?$"; + private const int StateMaxLength = 64; + private const string StateRegexPattern = "^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{L}+)*$"; + private const int ZipCodeMaxLength = 8; + private const string ZipCodeRegexPattern = "^[\\p{L}\\d\\s-]{3,}$"; + public static IEnumerable Validate(AddressDto address) { if (string.IsNullOrWhiteSpace(address.City)) @@ -13,12 +24,12 @@ public static IEnumerable Validate(AddressDto address) yield return new ValidationResult("City is required", [nameof(address.City)]); } - if (address.City.Length > 64) + if (address.City.Length > CityMaxLength) { yield return new ValidationResult("City is too long", [nameof(address.City)]); } - if (!new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{Lu}\\p{Ll}+)*$").IsMatch(address.City)) + if (!new Regex(CityRegexPattern).IsMatch(address.City)) { yield return new ValidationResult("City is invalid", [nameof(address.City)]); } @@ -28,12 +39,12 @@ public static IEnumerable Validate(AddressDto address) yield return new ValidationResult("Country is required", [nameof(address.Country)]); } - if (address.Country.Length > 64) + if (address.Country.Length > CountryMaxLength) { yield return new ValidationResult("Country is too long", [nameof(address.Country)]); } - if (!new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)(\\p{Lu}\\p{Ll}+|i|of|and|the)){0,5}$").IsMatch(address.Country)) + if (!new Regex(CountryRegexPattern).IsMatch(address.Country)) { yield return new ValidationResult("Country is invalid", [nameof(address.Country)]); } @@ -43,12 +54,12 @@ public static IEnumerable Validate(AddressDto address) yield return new ValidationResult("Street is required", [nameof(address.Street)]); } - if (address.Street.Length > 64) + if (address.Street.Length > StreetMaxLength) { yield return new ValidationResult("Street is too long", [nameof(address.Street)]); } - if (!new Regex("^[\\p{L}\\d]+(?:(\\s)\\p{L}+)*(\\s(?:(\\d+\\p{L}?(/\\d*\\p{L}?)?)))?$").IsMatch(address.Street)) + if (!new Regex(StreetRegexPattern).IsMatch(address.Street)) { yield return new ValidationResult("Street is invalid", [nameof(address.Street)]); } @@ -58,24 +69,24 @@ public static IEnumerable Validate(AddressDto address) yield return new ValidationResult("State is required", [nameof(address.State)]); } - if (address.State.Length > 64) + if (address.State.Length > StateMaxLength) { yield return new ValidationResult("State is too long", [nameof(address.State)]); } - if (!new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{L}+)*$").IsMatch(address.State)) + if (!new Regex(StateRegexPattern).IsMatch(address.State)) { yield return new ValidationResult("State is invalid", [nameof(address.State)]); } if (!string.IsNullOrWhiteSpace(address.ZipCode)) { - if (address.ZipCode.Length > 8) + if (address.ZipCode.Length > ZipCodeMaxLength) { yield return new ValidationResult("ZipCode is too long", [nameof(address.ZipCode)]); } - if (!new Regex("^[\\p{L}\\d\\s-]{3,}$").IsMatch(address.ZipCode)) + if (!new Regex(ZipCodeRegexPattern).IsMatch(address.ZipCode)) { yield return new ValidationResult("ZipCode is invalid", [nameof(address.ZipCode)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs index ea80de6c..f0d7efe8 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs @@ -5,6 +5,8 @@ namespace ReasnAPI.Validators { public class CommentValidator : IValidator { + private const int ContentMaxLength = 1024; + public static IEnumerable Validate(CommentDto comment) { if (string.IsNullOrWhiteSpace(comment.Content)) @@ -12,7 +14,7 @@ public static IEnumerable Validate(CommentDto comment) yield return new ValidationResult("Content is required", [nameof(comment.Content)]); } - if (comment.Content.Length > 1024) + if (comment.Content.Length > ContentMaxLength) { yield return new ValidationResult("Content is too long", [nameof(comment.Content)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs index cd35b64d..d313de3f 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs @@ -6,6 +6,11 @@ namespace ReasnAPI.Validators { public class EventValidator : IValidator { + private const int NameMaxLength = 64; + private const int DescriptionMaxLength = 4048; + private const int SlugMaxLength = 128; + private const string SlugRegexPattern = "^[\\p{L}\\d]+[\\p{L}\\d-]*$"; + public static IEnumerable Validate(EventDto eventData) { if (string.IsNullOrWhiteSpace(eventData.Name)) @@ -13,7 +18,7 @@ public static IEnumerable Validate(EventDto eventData) yield return new ValidationResult("Name is required", [nameof(eventData.Name)]); } - if (eventData.Name.Length > 64) + if (eventData.Name.Length > NameMaxLength) { yield return new ValidationResult("Name is too long", [nameof(eventData.Name)]); } @@ -23,7 +28,7 @@ public static IEnumerable Validate(EventDto eventData) yield return new ValidationResult("Description is required", [nameof(eventData.Description)]); } - if (eventData.Description.Length > 4048) + if (eventData.Description.Length > DescriptionMaxLength) { yield return new ValidationResult("Description is too long", [nameof(eventData.Description)]); } @@ -48,12 +53,12 @@ public static IEnumerable Validate(EventDto eventData) yield return new ValidationResult("Slug is required", [nameof(eventData.Slug)]); } - if (eventData.Slug.Length > 128) + if (eventData.Slug.Length > SlugMaxLength) { yield return new ValidationResult("Slug is too long", [nameof(eventData.Slug)]); } - if (!new Regex("^[\\p{L}\\d]+[\\p{L}\\d-]*$").IsMatch(eventData.Slug)) + if (!new Regex(SlugRegexPattern).IsMatch(eventData.Slug)) { yield return new ValidationResult("Slug is invalid", [nameof(eventData.Name)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs index d65fc8fb..6c93ada2 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs @@ -6,6 +6,9 @@ namespace ReasnAPI.Validators { public class InterestValidator : IValidator { + private const int NameMaxLength = 32; + private const string NameRegexPattern = "^\\p{Lu}\\p{Ll}+(?:\\s\\p{L}+)*$"; + public static IEnumerable Validate(IntrestDto interest) { if (string.IsNullOrWhiteSpace(interest.Name)) @@ -13,12 +16,12 @@ public static IEnumerable Validate(IntrestDto interest) yield return new ValidationResult("Name is required", [nameof(interest.Name)]); } - if (interest.Name.Length > 32) + if (interest.Name.Length > NameMaxLength) { yield return new ValidationResult("Name is too long", [nameof(interest.Name)]); } - if (!new Regex("^\\p{Lu}\\p{Ll}+(?:\\s\\p{L}+)*$").IsMatch(interest.Name)) + if (!new Regex(NameRegexPattern).IsMatch(interest.Name)) { yield return new ValidationResult("Name is invalid", [nameof(interest.Name)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs index c4e64206..4dca0be0 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs @@ -6,6 +6,11 @@ namespace ReasnAPI.Validators { public class ParameterValidator : IValidator { + private const int KeyMaxLength = 32; + private const string KeyRegexPattern = "^\\p{L}+(?:\\s\\p{L}+)*$"; + private const int ValueMaxLength = 64; + private const string ValueRegexPattern = "^[\\p{L}\\d]+(?:\\s[\\p{L}\\d]+)*$"; + public static IEnumerable Validate(ParameterDto parameter) { if (string.IsNullOrWhiteSpace(parameter.Key)) @@ -13,12 +18,12 @@ public static IEnumerable Validate(ParameterDto parameter) yield return new ValidationResult("Key is required", [nameof(parameter.Key)]); } - if (parameter.Key.Length > 32) + if (parameter.Key.Length > KeyMaxLength) { yield return new ValidationResult("Key is too long", [nameof(parameter.Key)]); } - if (!new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(parameter.Key)) + if (!new Regex(KeyRegexPattern).IsMatch(parameter.Key)) { yield return new ValidationResult("Key is invalid", [nameof(parameter.Key)]); } @@ -28,12 +33,12 @@ public static IEnumerable Validate(ParameterDto parameter) yield return new ValidationResult("Value is required", [nameof(parameter.Value)]); } - if (parameter.Value.Length > 64) + if (parameter.Value.Length > ValueMaxLength) { yield return new ValidationResult("Value is too long", [nameof(parameter.Value)]); } - if (!new Regex("^[\\p{L}\\d]+(?:\\s[\\p{L}\\d]+)*$").IsMatch(parameter.Value)) + if (!new Regex(ValueRegexPattern).IsMatch(parameter.Value)) { yield return new ValidationResult("Value is invalid", [nameof(parameter.Value)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs index f871c817..1691512d 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs @@ -6,6 +6,9 @@ namespace ReasnAPI.Validators { public class TagValidator : IValidator { + private const int NameMaxLength = 64; + private const string NameRegexPattern = "^\\p{L}+(?:\\s\\p{L}+)*$"; + public static IEnumerable Validate(TagDto tag) { if (string.IsNullOrWhiteSpace(tag.Name)) @@ -13,12 +16,12 @@ public static IEnumerable Validate(TagDto tag) yield return new ValidationResult("Name is required", [nameof(tag.Name)]); } - if (tag.Name.Length > 64) + if (tag.Name.Length > NameMaxLength) { yield return new ValidationResult("Name is too long", [nameof(tag.Name)]); } - if (!new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(tag.Name)) + if (!new Regex(NameRegexPattern).IsMatch(tag.Name)) { yield return new ValidationResult("Name is invalid", [nameof(tag.Name)]); } From 740fdcee8437403c4917d45fbe9ae280d76c4513 Mon Sep 17 00:00:00 2001 From: mkoper02 Date: Mon, 6 May 2024 18:11:26 +0200 Subject: [PATCH 10/24] Created basic validators for all models in db --- Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj | 1 - Server/ReasnAPI/ReasnAPI/Validators/.gitkeep | 0 .../ReasnAPI/Validators/AddressValidator.cs | 56 ++++++++++++ .../ReasnAPI/Validators/CommentValidator.cs | 42 +++++++++ .../ReasnAPI/Validators/EventValidator.cs | 81 +++++++++++++++++ .../ReasnAPI/Validators/IValidator.cs | 9 ++ .../ReasnAPI/Validators/ImageValidator.cs | 21 +++++ .../ReasnAPI/Validators/InterestValidator.cs | 21 +++++ .../Validators/ObjectTypeValidator.cs | 21 +++++ .../ReasnAPI/Validators/ParameterValidator.cs | 31 +++++++ .../ReasnAPI/Validators/RoleValidator.cs | 21 +++++ .../ReasnAPI/Validators/StatusValidator.cs | 26 ++++++ .../ReasnAPI/Validators/TagValidator.cs | 21 +++++ .../ReasnAPI/Validators/UserValidator.cs | 86 +++++++++++++++++++ 14 files changed, 436 insertions(+), 1 deletion(-) delete mode 100644 Server/ReasnAPI/ReasnAPI/Validators/.gitkeep create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/IValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs diff --git a/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj b/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj index 23499ae8..02ce3550 100644 --- a/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj +++ b/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj @@ -25,7 +25,6 @@ - diff --git a/Server/ReasnAPI/ReasnAPI/Validators/.gitkeep b/Server/ReasnAPI/ReasnAPI/Validators/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs new file mode 100644 index 00000000..a343a508 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs @@ -0,0 +1,56 @@ +using ReasnAPI.Models.Database; +using System.ComponentModel.DataAnnotations; + +namespace ReasnAPI.Validators +{ + public class AddressValidator : IValidator
+ { + public static IEnumerable Validate(Address address) + { + if (string.IsNullOrWhiteSpace(address.City)) + { + yield return new ValidationResult("City is required", [nameof(address.City)]); + } + + if (address.City.Length > 64) + { + yield return new ValidationResult("City is too long", [nameof(address.City)]); + } + + if (string.IsNullOrWhiteSpace(address.Country)) + { + yield return new ValidationResult("Country is required", [nameof(address.Country)]); + } + + if (address.Country.Length > 64) + { + yield return new ValidationResult("Country is too long", [nameof(address.Country)]); + } + + if (string.IsNullOrWhiteSpace(address.Street)) + { + yield return new ValidationResult("Street is required", [nameof(address.Street)]); + } + + if (address.Street.Length > 64) + { + yield return new ValidationResult("Street is too long", [nameof(address.Street)]); + } + + if (string.IsNullOrWhiteSpace(address.State)) + { + yield return new ValidationResult("State is required", [nameof(address.State)]); + } + + if (address.State.Length > 64) + { + yield return new ValidationResult("State is too long", [nameof(address.State)]); + } + + if (!string.IsNullOrWhiteSpace(address.ZipCode) && address.ZipCode.Length > 8 ) + { + yield return new ValidationResult("ZipCode is too long", [nameof(address.ZipCode)]); + } + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs new file mode 100644 index 00000000..e4fd2264 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs @@ -0,0 +1,42 @@ +using ReasnAPI.Models.Database; +using System.ComponentModel.DataAnnotations; +using System.Numerics; + +namespace ReasnAPI.Validators +{ + public class CommentValidator : IValidator + { + public static IEnumerable Validate(Comment comment) + { + if (string.IsNullOrWhiteSpace(comment.EventId.ToString())) + { + yield return new ValidationResult("EventId is required", [nameof(comment.EventId)]); + } + + if (string.IsNullOrWhiteSpace(comment.Content)) + { + yield return new ValidationResult("Content is required", [nameof(comment.Content)]); + } + + if (comment.Content.Length > 1024) + { + yield return new ValidationResult("Content is too long", [nameof(comment.Content)]); + } + + if (string.IsNullOrWhiteSpace(comment.CreatedAt.ToString())) + { + yield return new ValidationResult("CreatedAt is required", [nameof(comment.CreatedAt)]); + } + + if (comment.CreatedAt > DateTime.Now) + { + yield return new ValidationResult("CreatedAt is in the future", [nameof(comment.CreatedAt)]); + } + + if (string.IsNullOrWhiteSpace(comment.UserId.ToString())) + { + yield return new ValidationResult("UserId is required", [nameof(comment.UserId)]); + } + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs new file mode 100644 index 00000000..5cb71047 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs @@ -0,0 +1,81 @@ +using ReasnAPI.Models.Database; +using System.ComponentModel.DataAnnotations; + +namespace ReasnAPI.Validators +{ + public class EventValidator : IValidator + { + public static IEnumerable Validate(Event eventData) + { + if (string.IsNullOrWhiteSpace(eventData.Name)) + { + yield return new ValidationResult("Name is required", [nameof(eventData.Name)]); + } + + if (eventData.Name.Length > 64) + { + yield return new ValidationResult("Name is too long", [nameof(eventData.Name)]); + } + + if (string.IsNullOrWhiteSpace(eventData.AddressId.ToString())) + { + yield return new ValidationResult("AddressId is required", [nameof(eventData.AddressId)]); + } + + if (string.IsNullOrWhiteSpace(eventData.Description)) + { + yield return new ValidationResult("Description is required", [nameof(eventData.Description)]); + } + + if (eventData.Description.Length > 4048) + { + yield return new ValidationResult("Description is too long", [nameof(eventData.Description)]); + } + + if (string.IsNullOrWhiteSpace(eventData.OrganizerId.ToString())) + { + yield return new ValidationResult("OrganizerId is required", [nameof(eventData.OrganizerId)]); + } + + if (string.IsNullOrWhiteSpace(eventData.StartAt.ToString())) + { + yield return new ValidationResult("StartTime is required", [nameof(eventData.StartAt)]); + } + + if (string.IsNullOrWhiteSpace(eventData.EndAt.ToString())) + { + yield return new ValidationResult("EndTime is required", [nameof(eventData.EndAt)]); + } + + if (eventData.StartAt > eventData.EndAt) + { + yield return new ValidationResult("StartTime is after EndTime", [nameof(eventData.StartAt)]); + } + + if (string.IsNullOrWhiteSpace(eventData.CreatedAt.ToString())) + { + yield return new ValidationResult("CreatedAt is required", [nameof(eventData.CreatedAt)]); + } + + if (string.IsNullOrWhiteSpace(eventData.UpdatedAt.ToString())) + { + yield return new ValidationResult("UpdatedAt is required", [nameof(eventData.UpdatedAt)]); + } + + if (string.IsNullOrWhiteSpace(eventData.Slug)) + { + yield return new ValidationResult("Slug is required", [nameof(eventData.Slug)]); + } + + if (eventData.Slug.Length > 128) + { + yield return new ValidationResult("Slug is too long", [nameof(eventData.Slug)]); + } + + if (string.IsNullOrWhiteSpace(eventData.StatusId.ToString())) + { + yield return new ValidationResult("StatusId is required", [nameof(eventData.StatusId)]); + } + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/IValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/IValidator.cs new file mode 100644 index 00000000..12db5b9b --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/IValidator.cs @@ -0,0 +1,9 @@ +using System.ComponentModel.DataAnnotations; + +namespace ReasnAPI.Validators +{ + public interface IValidator + { + static abstract IEnumerable Validate(T objectToValidate); + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs new file mode 100644 index 00000000..15de2bfc --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs @@ -0,0 +1,21 @@ +using ReasnAPI.Models.Database; +using System.ComponentModel.DataAnnotations; + +namespace ReasnAPI.Validators +{ + public class ImageValidator : IValidator + { + public static IEnumerable Validate(Image image) + { + if (string.IsNullOrWhiteSpace(image.ObjectTypeId.ToString())) + { + yield return new ValidationResult("ObjectTypeId is required", [nameof(image.ObjectTypeId)]); + } + + if (string.IsNullOrWhiteSpace(image.ObjectId.ToString())) + { + yield return new ValidationResult("ObjectId is required", [nameof(image.ObjectId)]); + } + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs new file mode 100644 index 00000000..4729cb1e --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs @@ -0,0 +1,21 @@ +using ReasnAPI.Models.Database; +using System.ComponentModel.DataAnnotations; + +namespace ReasnAPI.Validators +{ + public class InterestValidator : IValidator + { + public static IEnumerable Validate(Interest interest) + { + if (string.IsNullOrWhiteSpace(interest.Name)) + { + yield return new ValidationResult("Name is required", [nameof(interest.Name)]); + } + + if (interest.Name.Length > 32) + { + yield return new ValidationResult("Name is too long", [nameof(interest.Name)]); + } + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs new file mode 100644 index 00000000..db634df6 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs @@ -0,0 +1,21 @@ +using ReasnAPI.Models.Database; +using System.ComponentModel.DataAnnotations; + +namespace ReasnAPI.Validators +{ + public class ObjectTypeValidator : IValidator + { + public static IEnumerable Validate(ObjectType objectType) + { + if (string.IsNullOrWhiteSpace(objectType.Name)) + { + yield return new ValidationResult("Name is required", [nameof(objectType.Name)]); + } + + if (objectType.Name.Length > 32) + { + yield return new ValidationResult("Name is too long", [nameof(objectType.Name)]); + } + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs new file mode 100644 index 00000000..b5271925 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs @@ -0,0 +1,31 @@ +using ReasnAPI.Models.Database; +using System.ComponentModel.DataAnnotations; + +namespace ReasnAPI.Validators +{ + public class ParameterValidator : IValidator + { + public static IEnumerable Validate(Parameter parameter) + { + if (string.IsNullOrWhiteSpace(parameter.Key)) + { + yield return new ValidationResult("Key is required", [nameof(parameter.Key)]); + } + + if (parameter.Key.Length > 32) + { + yield return new ValidationResult("Key is too long", [nameof(parameter.Key)]); + } + + if (string.IsNullOrWhiteSpace(parameter.Value)) + { + yield return new ValidationResult("Value is required", [nameof(parameter.Value)]); + } + + if (parameter.Value.Length > 64) + { + yield return new ValidationResult("Value is too long", [nameof(parameter.Value)]); + } + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs new file mode 100644 index 00000000..119b2f9d --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs @@ -0,0 +1,21 @@ +using ReasnAPI.Models.Database; +using System.ComponentModel.DataAnnotations; + +namespace ReasnAPI.Validators +{ + public class RoleValidator : IValidator + { + public static IEnumerable Validate(Role role) + { + if (string.IsNullOrWhiteSpace(role.Name)) + { + yield return new ValidationResult("Role name is required", [nameof(role.Name)]); + } + + if (role.Name.Length > 32) + { + yield return new ValidationResult("Role name is too long", [nameof(role.Name)]); + } + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs new file mode 100644 index 00000000..579f0faa --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs @@ -0,0 +1,26 @@ +using ReasnAPI.Models.Database; +using System.ComponentModel.DataAnnotations; + +namespace ReasnAPI.Validators +{ + public class StatusValidator : IValidator + { + public static IEnumerable Validate(Status status) + { + if (string.IsNullOrWhiteSpace(status.Name)) + { + yield return new ValidationResult("Name is required", [nameof(status.Name)]); + } + + if (status.Name.Length > 32) + { + yield return new ValidationResult("Name is too long", [nameof(status.Name)]); + } + + if (string.IsNullOrWhiteSpace(status.ObjectTypeId.ToString())) + { + yield return new ValidationResult("ObjectTypeId is required", [nameof(status.ObjectTypeId)]); + } + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs new file mode 100644 index 00000000..ecae1929 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs @@ -0,0 +1,21 @@ +using ReasnAPI.Models.Database; +using System.ComponentModel.DataAnnotations; + +namespace ReasnAPI.Validators +{ + public class TagValidator : IValidator + { + public static IEnumerable Validate(Tag tag) + { + if (string.IsNullOrWhiteSpace(tag.Name)) + { + yield return new ValidationResult("Name is required", [nameof(tag.Name)]); + } + + if (tag.Name.Length > 64) + { + yield return new ValidationResult("Name is too long", [nameof(tag.Name)]); + } + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs new file mode 100644 index 00000000..56da2983 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs @@ -0,0 +1,86 @@ +using ReasnAPI.Models.Database; +using System.ComponentModel.DataAnnotations; + +namespace ReasnAPI.Validators +{ + public class UserValidator : IValidator + { + public static IEnumerable Validate(User user) + { + if (string.IsNullOrWhiteSpace(user.Name)) + { + yield return new ValidationResult("Name is required", [nameof(user.Name)]); + } + + if (user.Name.Length > 64) + { + yield return new ValidationResult("Name is too long", [nameof(user.Name)]); + } + + if (string.IsNullOrWhiteSpace(user.Surname)) + { + yield return new ValidationResult("Surname is required", [nameof(user.Surname)]); + } + + if (user.Surname.Length > 64) + { + yield return new ValidationResult("Surname is too long", [nameof(user.Surname)]); + } + + if (string.IsNullOrWhiteSpace(user.Username)) + { + yield return new ValidationResult("Username is required", [nameof(user.Username)]); + } + + if (user.Username.Length > 64) + { + yield return new ValidationResult("Username is too long", [nameof(user.Username)]); + } + + if (string.IsNullOrWhiteSpace(user.Password)) + { + yield return new ValidationResult("Password is required", [nameof(user.Password)]); + } + + if (string.IsNullOrWhiteSpace(user.CreatedAt.ToString())) + { + yield return new ValidationResult("CreatedAt is required", [nameof(user.CreatedAt)]); + } + + if (string.IsNullOrWhiteSpace(user.UpdatedAt.ToString())) + { + yield return new ValidationResult("UpdatedAt is required", [nameof(user.UpdatedAt)]); + } + + if (string.IsNullOrWhiteSpace(user.RoleId.ToString())) + { + yield return new ValidationResult("RoleId is required", [nameof(user.RoleId)]); + } + + if (string.IsNullOrWhiteSpace(user.Email)) + { + yield return new ValidationResult("Email is required", [nameof(user.Email)]); + } + + if (user.Email.Length > 255) + { + yield return new ValidationResult("Email is too long", [nameof(user.Email)]); + } + + if (string.IsNullOrWhiteSpace(user.AddressId.ToString())) + { + yield return new ValidationResult("AddressId is required", [nameof(user.AddressId)]); + } + + if (string.IsNullOrWhiteSpace(user.Phone)) + { + yield return new ValidationResult("Phone is required", [nameof(user.Phone)]); + } + + if (!string.IsNullOrWhiteSpace(user.Phone) && user.Phone.Length > 16) + { + yield return new ValidationResult("Phone is too long", [nameof(user.Phone)]); + } + } + } +} From 5c611e9199b1db4b6c821e1316dac112884c51a0 Mon Sep 17 00:00:00 2001 From: mkoper02 Date: Sat, 11 May 2024 18:48:50 +0200 Subject: [PATCH 11/24] Created regex check for all models --- .../ReasnAPI/Validators/AddressValidator.cs | 33 ++++++++++++++++- .../ReasnAPI/Validators/EventValidator.cs | 6 +++ .../ReasnAPI/Validators/InterestValidator.cs | 6 +++ .../Validators/ObjectTypeValidator.cs | 6 +++ .../ReasnAPI/Validators/ParameterValidator.cs | 11 ++++++ .../ReasnAPI/Validators/RoleValidator.cs | 6 +++ .../ReasnAPI/Validators/StatusValidator.cs | 6 +++ .../ReasnAPI/Validators/TagValidator.cs | 6 +++ .../ReasnAPI/Validators/UserValidator.cs | 37 ++++++++++++++++--- 9 files changed, 109 insertions(+), 8 deletions(-) diff --git a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs index a343a508..08aa4c60 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs @@ -1,5 +1,6 @@ using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; +using System.Text.RegularExpressions; namespace ReasnAPI.Validators { @@ -17,6 +18,11 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("City is too long", [nameof(address.City)]); } + if (new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{Lu}\\p{Ll}+)*$").IsMatch(address.City) is false) + { + yield return new ValidationResult("City is invalid", [nameof(address.City)]); + } + if (string.IsNullOrWhiteSpace(address.Country)) { yield return new ValidationResult("Country is required", [nameof(address.Country)]); @@ -27,6 +33,11 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("Country is too long", [nameof(address.Country)]); } + if (new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)(\\p{Lu}\\p{Ll}+|i|of|and|the)){0,5}$").IsMatch(address.Country) is false) + { + yield return new ValidationResult("Country is invalid", [nameof(address.Country)]); + } + if (string.IsNullOrWhiteSpace(address.Street)) { yield return new ValidationResult("Street is required", [nameof(address.Street)]); @@ -37,6 +48,11 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("Street is too long", [nameof(address.Street)]); } + if (new Regex("^[\\p{L}\\d]+(?:(\\s)\\p{L}+)*(\\s(?:(\\d+\\p{L}?(/\\d*\\p{L}?)?)))?$").IsMatch(address.Street) is false) + { + yield return new ValidationResult("Street is invalid", [nameof(address.Street)]); + } + if (string.IsNullOrWhiteSpace(address.State)) { yield return new ValidationResult("State is required", [nameof(address.State)]); @@ -47,9 +63,22 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("State is too long", [nameof(address.State)]); } - if (!string.IsNullOrWhiteSpace(address.ZipCode) && address.ZipCode.Length > 8 ) + if (new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{L}+)*$").IsMatch(address.State) is false) + { + yield return new ValidationResult("State is invalid", [nameof(address.State)]); + } + + if (!string.IsNullOrWhiteSpace(address.ZipCode)) { - yield return new ValidationResult("ZipCode is too long", [nameof(address.ZipCode)]); + if (address.ZipCode.Length > 8) + { + yield return new ValidationResult("ZipCode is too long", [nameof(address.ZipCode)]); + } + + if (new Regex("^[\\p{L}\\d\\s-]{3,}$").IsMatch(address.ZipCode) is false) + { + yield return new ValidationResult("ZipCode is invalid", [nameof(address.ZipCode)]); + } } } } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs index 5cb71047..87de07e9 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs @@ -1,5 +1,6 @@ using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; +using System.Text.RegularExpressions; namespace ReasnAPI.Validators { @@ -72,6 +73,11 @@ public static IEnumerable Validate(Event eventData) yield return new ValidationResult("Slug is too long", [nameof(eventData.Slug)]); } + if (new Regex("^[\\p{L}\\d]+[\\p{L}\\d-]*$").IsMatch(eventData.Slug)) + { + yield return new ValidationResult("Slug is invalid", [nameof(eventData.Name)]); + } + if (string.IsNullOrWhiteSpace(eventData.StatusId.ToString())) { yield return new ValidationResult("StatusId is required", [nameof(eventData.StatusId)]); diff --git a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs index 4729cb1e..ce4704ed 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs @@ -1,5 +1,6 @@ using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; +using System.Text.RegularExpressions; namespace ReasnAPI.Validators { @@ -16,6 +17,11 @@ public static IEnumerable Validate(Interest interest) { yield return new ValidationResult("Name is too long", [nameof(interest.Name)]); } + + if (new Regex("^\\p{Lu}\\p{Ll}+(?:\\s\\p{L}+)*$").IsMatch(interest.Name)) + { + yield return new ValidationResult("Name is invalid", [nameof(interest.Name)]); + } } } } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs index db634df6..c26bddaf 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs @@ -1,5 +1,6 @@ using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; +using System.Text.RegularExpressions; namespace ReasnAPI.Validators { @@ -16,6 +17,11 @@ public static IEnumerable Validate(ObjectType objectType) { yield return new ValidationResult("Name is too long", [nameof(objectType.Name)]); } + + if (new Regex("^(Event|User)$").IsMatch(objectType.Name) is false) + { + yield return new ValidationResult("Name is invalid", [nameof(objectType.Name)]); + } } } } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs index b5271925..8a06fe21 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs @@ -1,5 +1,6 @@ using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; +using System.Text.RegularExpressions; namespace ReasnAPI.Validators { @@ -17,6 +18,11 @@ public static IEnumerable Validate(Parameter parameter) yield return new ValidationResult("Key is too long", [nameof(parameter.Key)]); } + if (new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(parameter.Key)) + { + yield return new ValidationResult("Key is invalid", [nameof(parameter.Key)]); + } + if (string.IsNullOrWhiteSpace(parameter.Value)) { yield return new ValidationResult("Value is required", [nameof(parameter.Value)]); @@ -26,6 +32,11 @@ public static IEnumerable Validate(Parameter parameter) { yield return new ValidationResult("Value is too long", [nameof(parameter.Value)]); } + + if (new Regex("^[\\p{L}\\d]+(?:\\s[\\p{L}\\d]+)*$").IsMatch(parameter.Value)) + { + yield return new ValidationResult("Value is invalid", [nameof(parameter.Value)]); + } } } } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs index 119b2f9d..362a9fc9 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs @@ -1,5 +1,6 @@ using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; +using System.Text.RegularExpressions; namespace ReasnAPI.Validators { @@ -16,6 +17,11 @@ public static IEnumerable Validate(Role role) { yield return new ValidationResult("Role name is too long", [nameof(role.Name)]); } + + if (new Regex("^(Organizer|Admin|User)$").IsMatch(role.Name) is false) + { + yield return new ValidationResult("Role name is invalid", [nameof(role.Name)]); + } } } } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs index 579f0faa..a28e7bb1 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs @@ -1,5 +1,6 @@ using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; +using System.Text.RegularExpressions; namespace ReasnAPI.Validators { @@ -21,6 +22,11 @@ public static IEnumerable Validate(Status status) { yield return new ValidationResult("ObjectTypeId is required", [nameof(status.ObjectTypeId)]); } + + if (new Regex("^(Interested|Participating|Completed|In progress|Waiting for approval)$").IsMatch(status.Name) is false) + { + yield return new ValidationResult("Name is invalid", [nameof(status.Name)]); + } } } } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs index ecae1929..ff7ee67c 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs @@ -1,5 +1,6 @@ using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; +using System.Text.RegularExpressions; namespace ReasnAPI.Validators { @@ -16,6 +17,11 @@ public static IEnumerable Validate(Tag tag) { yield return new ValidationResult("Name is too long", [nameof(tag.Name)]); } + + if (new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(tag.Name)) + { + yield return new ValidationResult("Name is invalid", [nameof(tag.Name)]); + } } } } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs index 56da2983..b6dfb0d0 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs @@ -1,5 +1,6 @@ using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; +using System.Text.RegularExpressions; namespace ReasnAPI.Validators { @@ -17,6 +18,11 @@ public static IEnumerable Validate(User user) yield return new ValidationResult("Name is too long", [nameof(user.Name)]); } + if (new Regex("^\\p{Lu}\\p{Ll}+$").IsMatch(user.Name) is false) + { + yield return new ValidationResult("Name is invalid", [nameof(user.Name)]); + } + if (string.IsNullOrWhiteSpace(user.Surname)) { yield return new ValidationResult("Surname is required", [nameof(user.Surname)]); @@ -27,6 +33,11 @@ public static IEnumerable Validate(User user) yield return new ValidationResult("Surname is too long", [nameof(user.Surname)]); } + if (new Regex("^\\p{L}+(?:[\\s'-]?\\p{L}+)*$").IsMatch(user.Surname) is false) + { + yield return new ValidationResult("Surname is invalid", [nameof(user.Surname)]); + } + if (string.IsNullOrWhiteSpace(user.Username)) { yield return new ValidationResult("Username is required", [nameof(user.Username)]); @@ -37,6 +48,11 @@ public static IEnumerable Validate(User user) yield return new ValidationResult("Username is too long", [nameof(user.Username)]); } + if (new Regex("^[\\p{L}\\d._%+-]+$").IsMatch(user.Username) is false) + { + yield return new ValidationResult("Username is invalid", [nameof(user.Username)]); + } + if (string.IsNullOrWhiteSpace(user.Password)) { yield return new ValidationResult("Password is required", [nameof(user.Password)]); @@ -67,20 +83,29 @@ public static IEnumerable Validate(User user) yield return new ValidationResult("Email is too long", [nameof(user.Email)]); } - if (string.IsNullOrWhiteSpace(user.AddressId.ToString())) + if (new Regex("^[a-zA-Z\\d._%+-]+@[a-zA-Z\\d.-]+\\.[a-zA-Z]{2,6}$").IsMatch(user.Email) is false) { - yield return new ValidationResult("AddressId is required", [nameof(user.AddressId)]); + yield return new ValidationResult("Email is invalid", [nameof(user.Email)]); } - if (string.IsNullOrWhiteSpace(user.Phone)) + if (string.IsNullOrWhiteSpace(user.AddressId.ToString())) { - yield return new ValidationResult("Phone is required", [nameof(user.Phone)]); + yield return new ValidationResult("AddressId is required", [nameof(user.AddressId)]); } - if (!string.IsNullOrWhiteSpace(user.Phone) && user.Phone.Length > 16) + if (!string.IsNullOrWhiteSpace(user.Phone)) { - yield return new ValidationResult("Phone is too long", [nameof(user.Phone)]); + if (!string.IsNullOrWhiteSpace(user.Phone) && user.Phone.Length > 16) + { + yield return new ValidationResult("Phone is too long", [nameof(user.Phone)]); + } + + if (new Regex("^\\+\\d{1,3}\\s\\d{1,15}$").IsMatch(user.Phone) is false) + { + yield return new ValidationResult("Phone is invalid", [nameof(user.Phone)]); + } } + } } } From 3c3a10b71a1c880221a6acf86d7b381d22d570a6 Mon Sep 17 00:00:00 2001 From: Maciej Koperdowski Date: Mon, 13 May 2024 19:49:10 +0200 Subject: [PATCH 12/24] Added regex in validators, changed models into dtos, created unit tests --- .../ReasnAPI.Tests/ReasnAPI.Tests.csproj | 4 + Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs | 12 - .../Validators/AddressValidatorTests.cs | 336 ++++++++++++++++ .../Validators/CommentValidatorTests.cs | 65 +++ .../Validators/EventValidatorTests.cs | 257 ++++++++++++ .../Validators/InterestValidatorTests.cs | 62 +++ .../Validators/ObjectTypeValidatorTests.cs | 75 ++++ .../Validators/ParameterValidatorTests.cs | 109 +++++ .../Validators/RoleValidatorTests.cs | 75 ++++ .../Validators/StatusValidatorTests.cs | 101 +++++ .../Validators/TagValidatorTests.cs | 62 +++ .../Validators/UserValidatorTests.cs | 374 ++++++++++++++++++ .../ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs | 4 +- Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj | 1 - .../ReasnAPI/Validators/AddressValidator.cs | 16 +- .../ReasnAPI/Validators/CommentValidator.cs | 24 +- .../ReasnAPI/Validators/EventValidator.cs | 41 +- .../ReasnAPI/Validators/ImageValidator.cs | 21 - .../ReasnAPI/Validators/InterestValidator.cs | 8 +- .../Validators/ObjectTypeValidator.cs | 2 +- .../ReasnAPI/Validators/ParameterValidator.cs | 10 +- .../ReasnAPI/Validators/RoleValidator.cs | 13 +- .../ReasnAPI/Validators/StatusValidator.cs | 18 +- .../ReasnAPI/Validators/TagValidator.cs | 8 +- .../ReasnAPI/Validators/UserValidator.cs | 43 +- 25 files changed, 1573 insertions(+), 168 deletions(-) delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/AddressValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs diff --git a/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj b/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj index 1b46a3ed..44463a72 100644 --- a/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj +++ b/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj @@ -17,6 +17,10 @@ + + + + diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs deleted file mode 100644 index 46dac6f2..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace ReasnAPI.Tests -{ - [TestClass] - public class UnitTest1 - { - [TestMethod] - public void TestAdd() - { - Assert.AreEqual(17, 17); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/AddressValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/AddressValidatorTests.cs new file mode 100644 index 00000000..0ff447ab --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/AddressValidatorTests.cs @@ -0,0 +1,336 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class AddressValidatorTests + { + [TestMethod] + public void Validate_WhenCityIsEmpty_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "", + Country = "Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "City is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "City is invalid")); + } + + [TestMethod] + public void Validate_WhenCityIsTooLong_ReturnsValidationResult() + { + var address = new AddressDto + { + City = new string('a', 65), + Country = "Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "City is too long")); + } + + [TestMethod] + public void Validate_WhenCityIsInvalid_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "Invalid City", + Country = "Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "City is invalid")); + } + + [TestMethod] + public void Validate_WhenCityIsValid_ReturnsNoValidationResult() + { + var address = new AddressDto + { + City = "Valid City", + Country = "Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenCountryIsEmpty_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Country is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Country is invalid")); + } + + [TestMethod] + public void Validate_WhenCountryIsTooLong_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = new string('a', 65), + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Country is too long")); + } + + [TestMethod] + public void Validate_WhenCountryIsInvalid_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Invalid Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Country is invalid")); + } + + [TestMethod] + public void Validate_WhenCountryIsValid_ReturnsNoValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Valid Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenStreetIsEmpty_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Street is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Street is invalid")); + } + + [TestMethod] + public void Validate_WhenStreetIsTooLong_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = new string('a', 65), + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Street is too long")); + } + + [TestMethod] + public void Validate_WhenStreetIsInvalid_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Invalid Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Street is invalid")); + } + + [TestMethod] + public void Validate_WhenStreetIsValid_ReturnsNoValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Valid Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenStateIsEmpty_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = "", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "State is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "State is invalid")); + } + + [TestMethod] + public void Validate_WhenStateIsTooLong_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = new string('a', 65), + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "State is too long")); + } + + [TestMethod] + public void Validate_WhenStateIsInvalid_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = "Invalid State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "State is invalid")); + } + + [TestMethod] + public void Validate_WhenStateIsValid_ReturnsNoValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = "Valid State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Valdate_WhenZipCodeIsTooLong_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = "State", + ZipCode = new string('0', 9) + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "ZipCode is too long")); + } + + [TestMethod] + public void Validate_WhenZipCodeIsInvalid_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = "State", + ZipCode = "Invalid_" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "ZipCode is invalid")); + } + + [TestMethod] + public void Validate_WhenZipCodeIsValid_ReturnsNoValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsFalse(result.Any()); + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs new file mode 100644 index 00000000..49f64da6 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs @@ -0,0 +1,65 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class CommentValidatorTests + { + [TestMethod] + public void Validate_WhenContentIsEmpty_ReturnsValidationResult() + { + var comment = new CommentDto + { + Content = "", + CreatedAt = DateTime.Now + }; + + var result = CommentValidator.Validate(comment); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Content is required")); + } + + [TestMethod] + public void Validate_WhenContentIsTooLong_ReturnsValidationResult() + { + var comment = new CommentDto + { + Content = new string('a', 1025), + CreatedAt = DateTime.Now + }; + + var result = CommentValidator.Validate(comment); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Content is too long")); + } + + [TestMethod] + public void Validate_WhenCreatedAtIsInTheFuture_ReturnsValidationResult() + { + var comment = new CommentDto + { + Content = "Content", + CreatedAt = DateTime.Now.AddMinutes(1) + }; + + var result = CommentValidator.Validate(comment); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "CreatedAt is in the future")); + } + + [TestMethod] + public void Validate_WhenCommentIsValid_ReturnsNoValidationResult() + { + var comment = new CommentDto + { + Content = "Content", + CreatedAt = DateTime.Now + }; + + var result = CommentValidator.Validate(comment); + + Assert.IsFalse(result.Any()); + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs new file mode 100644 index 00000000..ce6b68ff --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs @@ -0,0 +1,257 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class EventValidatorTests + { + [TestMethod] + public void Validate_WhenNameIsEmpty_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); + } + + [TestMethod] + public void Validate_WhenNameIsTooLong_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = new string('a', 65), + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); + } + + [TestMethod] + public void Validate_WhenNameIsValid_ReturnsNoValidationResult() + { + var event1 = new EventDto + { + Name = "ValidName", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenDescriptionIsEmpty_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Description is required")); + } + + [TestMethod] + public void Validate_WhenDescriptionIsTooLong_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = new string('a', 4049), + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Description is too long")); + } + + [TestMethod] + public void Validate_WhenDescriptionIsValid_ReturnsNoValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Valid Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenStartAtIsAfterEndAt_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now.AddMinutes(1), + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "StartTime is after EndTime")); + } + + [TestMethod] + public void Validate_WhenCreatedAtIsInTheFuture_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now.AddMinutes(1), + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "CreatedAt is in the future")); + } + + [TestMethod] + public void Validate_WhenUpdatedAtIsInTheFuture_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now.AddMinutes(1), + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "UpdatedAt is in the future")); + } + + [TestMethod] + public void Validate_WhenSlugIsEmpty_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is invalid")); + } + + [TestMethod] + public void Validate_WhenSlugIsTooLong_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = new string('a', 129) + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is too long")); + } + + [TestMethod] + public void Validate_WhenSlugIsIsInvalid_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "invalid slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is invalid")); + } + + [TestMethod] + public void Validate_WhenSlugIsValid_ReturnsNoValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "valid-slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsFalse(result.Any()); + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs new file mode 100644 index 00000000..4d64732a --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs @@ -0,0 +1,62 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class InterestValidatorTests + { + [TestMethod] + public void Validate_WhenNameIsEmpty_ReturnsValidationResult() + { + var interest = new IntrestDto + { + Name = "" + }; + + var result = InterestValidator.Validate(interest); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsTooLong_ReturnsValidationResult() + { + var interest = new IntrestDto + { + Name = new string('a', 33) + }; + + var result = InterestValidator.Validate(interest); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); + } + + [TestMethod] + public void Validate_WhenNameIsInvalid_ReturnsValidationResult() + { + var interest = new IntrestDto + { + Name = "Invalid Name" + }; + + var result = InterestValidator.Validate(interest); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsValid_ReturnsNoValidationResult() + { + var interest = new IntrestDto + { + Name = "Valid Name" + }; + + var result = InterestValidator.Validate(interest); + + Assert.IsFalse(result.Any()); + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs new file mode 100644 index 00000000..5c1480ee --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs @@ -0,0 +1,75 @@ +using ReasnAPI.Models.Database; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class ObjectTypeValidatorTests + { + [TestMethod] + public void Validate_WhenNameIsEmpty_ReturnsValidationResult() + { + var objectType = new ObjectType + { + Name = "" + }; + + var result = ObjectTypeValidator.Validate(objectType); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsTooLong_ReturnsValidationResult() + { + var objectType = new ObjectType + { + Name = new string('a', 33) + }; + + var result = ObjectTypeValidator.Validate(objectType); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); + } + + [TestMethod] + public void Validate_WhenNameIsInvalid_ReturnsValidationResult() + { + var objectType = new ObjectType + { + Name = "Invalid Name" + }; + + var result = ObjectTypeValidator.Validate(objectType); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsEvent_ReturnsNoValidationResult() + { + var objectType = new ObjectType + { + Name = "Event" + }; + + var result = ObjectTypeValidator.Validate(objectType); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenNameIsUser_ReturnsNoValidationResult() + { + var objectType = new ObjectType + { + Name = "User" + }; + + var result = ObjectTypeValidator.Validate(objectType); + + Assert.IsFalse(result.Any()); + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs new file mode 100644 index 00000000..424f987b --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs @@ -0,0 +1,109 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class ParameterValidatorTests + { + [TestMethod] + public void Validate_WhenKeyIsEmpty_ReturnsKeyIsRequired() + { + var parameter = new ParameterDto + { + Key = "", + Value = "value" + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is invalid")); + } + + [TestMethod] + public void Validate_WhenKeyIsTooLong_ReturnsKeyIsTooLong() + { + var parameter = new ParameterDto + { + Key = new string('a', 33), + Value = "value" + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is too long")); + } + + [TestMethod] + public void Validate_WhenKeyIsInvalid_ReturnsKeyIsInvalid() + { + var parameter = new ParameterDto + { + Key = "Invalid Key", + Value = "value" + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is invalid")); + } + + [TestMethod] + public void Validate_WhenValueIsEmpty_ReturnsValueIsRequired() + { + var parameter = new ParameterDto + { + Key = "key", + Value = "" + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is invalid")); + } + + [TestMethod] + public void Validate_WhenValueIsTooLong_ReturnsValueIsTooLong() + { + var parameter = new ParameterDto + { + Key = "key", + Value = new string('a', 65) + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is too long")); + } + + [TestMethod] + public void Validate_WhenValueIsInvalid_ReturnsValueIsInvalid() + { + var parameter = new ParameterDto + { + Key = "key", + Value = "Invalid Value" + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is invalid")); + } + + [TestMethod] + public void Validate_WhenValueAndKeyAreValid_ReturnsNoValidationResult() + { + var parameter = new ParameterDto + { + Key = "key", + Value = "value" + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsFalse(result.Any()); + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs new file mode 100644 index 00000000..a662254a --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs @@ -0,0 +1,75 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class RoleValidatorTests + { + [TestMethod] + public void Validate_WhenRoleNameIsEmpty_ReturnsValidationResult() + { + var role = new RoleDto + { + Name = "" + }; + + var result = RoleValidator.Validate(role); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Role name is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Role name is invalid")); + } + + [TestMethod] + public void Validate_WhenRoleNameIsInvalid_ReturnsValidationResult() + { + var role = new RoleDto + { + Name = "Invalid Role" + }; + + var result = RoleValidator.Validate(role); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Role name is invalid")); + } + + [TestMethod] + public void Validate_WhenRoleNameIsOrganizer_ReturnsNoValidationResult() + { + var role = new RoleDto + { + Name = "Organizer" + }; + + var result = RoleValidator.Validate(role); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenRoleNameIsAdmin_ReturnsNoValidationResult() + { + var role = new RoleDto + { + Name = "Admin" + }; + + var result = RoleValidator.Validate(role); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenRoleNameIsUser_ReturnsNoValidationResult() + { + var role = new RoleDto + { + Name = "User" + }; + + var result = RoleValidator.Validate(role); + + Assert.IsFalse(result.Any()); + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs new file mode 100644 index 00000000..c3438cdf --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs @@ -0,0 +1,101 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class StatusValidatorTests + { + [TestMethod] + public void Validate_WhenNameIsEmpty_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsInvalid_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "Invalid Name" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsInterested_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "Interested" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsParticipating_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "Participating" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsCompleted_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "Completed" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsInProgress_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "In progress" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsWaitingForApproval_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "Waiting for approval" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs new file mode 100644 index 00000000..4a935bdd --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs @@ -0,0 +1,62 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class TagValidatorTests + { + [TestMethod] + public void Validate_WhenNameIsEmpty_ReturnsValidationResult() + { + var tag = new TagDto + { + Name = "" + }; + + var result = TagValidator.Validate(tag); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsTooLong_ReturnsValidationResult() + { + var tag = new TagDto + { + Name = new string('a', 65) + }; + + var result = TagValidator.Validate(tag); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); + } + + [TestMethod] + public void Validate_WhenNameIsInvalid_ReturnsValidationResult() + { + var tag = new TagDto + { + Name = "Invalid Name" + }; + + var result = TagValidator.Validate(tag); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsValid_ReturnsValidationResult() + { + var tag = new TagDto + { + Name = "Valid Name" + }; + + var result = TagValidator.Validate(tag); + + Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs new file mode 100644 index 00000000..a5de2ecf --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs @@ -0,0 +1,374 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class UserValidatorTests + { + [TestMethod] + public void Validate_WhenNameIsEmpty_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsTooLong_ReturnsValidationResult() + { + var user = new UserDto + { + Name = new string('a', 65), + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); + } + + [TestMethod] + public void Validate_WhenNameIsInvalid_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Invalid Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsValid_ReturnsNoValidationResult() + { + var user = new UserDto + { + Name = "Validname", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenSurnameIsEmpty_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is invalid")); + } + + [TestMethod] + public void Validate_WhenSurnameIsTooLong_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = new string('a', 65), + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is too long")); + } + + [TestMethod] + public void Validate_WhenSurnameIsInvalid_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Invalid Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is invalid")); + } + + [TestMethod] + public void Validate_WhenSurnameIsValid_ReturnsNoValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Validsurname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenUsernameIsEmpty_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is invalid")); + } + + [TestMethod] + public void Validate_WhenUsernameIsTooLong_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = new string('a', 65), + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is too long")); + } + + [TestMethod] + public void Validate_WhenUsernameIsInvalid_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Invalid Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is invalid")); + } + + [TestMethod] + public void Validate_WhenUsernameIsValid_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "ValidUsername", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenEmailIsEmpty_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is invalid")); + } + + [TestMethod] + public void Validate_WhenEmailIsTooLong_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = new string('a', 256), + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is too long")); + } + + [TestMethod] + public void Validate_WhenEmailIsInvalid_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "Invalid Email", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is invalid")); + } + + [TestMethod] + public void Validate_WhenEmailIsValid_ReturnsNoValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "valid@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenPhoneIsTooLong_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = new string('a', 20) + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Phone is too long")); + } + + [TestMethod] + public void Validate_WhenPhoneIsInvalid_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "Invalid Phone" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Phone is invalid")); + } + + [TestMethod] + public void Validate_WhenPhoneIsValid_ReturnsNoValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsFalse(result.Any()); + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs b/Server/ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs index 5a55c085..d2e2eb46 100644 --- a/Server/ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs +++ b/Server/ReasnAPI/ReasnAPI/Models/DTOs/EventDto.cs @@ -1,8 +1,8 @@ using ReasnAPI.Models.Enums; -namespace ReasnAPI.Models.DTOs +namespace ReasnAPI.Models.DTOs { - public class EventDto + public class EventDto { public string Name { get; set; } = null!; public int AddressId { get; set; } diff --git a/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj b/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj index 02ce3550..a5564cb9 100644 --- a/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj +++ b/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj @@ -23,7 +23,6 @@ - diff --git a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs index 08aa4c60..e6c9897c 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class AddressValidator : IValidator
+ public class AddressValidator : IValidator { - public static IEnumerable Validate(Address address) + public static IEnumerable Validate(AddressDto address) { if (string.IsNullOrWhiteSpace(address.City)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("City is too long", [nameof(address.City)]); } - if (new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{Lu}\\p{Ll}+)*$").IsMatch(address.City) is false) + if (!new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{Lu}\\p{Ll}+)*$").IsMatch(address.City)) { yield return new ValidationResult("City is invalid", [nameof(address.City)]); } @@ -33,7 +33,7 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("Country is too long", [nameof(address.Country)]); } - if (new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)(\\p{Lu}\\p{Ll}+|i|of|and|the)){0,5}$").IsMatch(address.Country) is false) + if (!new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)(\\p{Lu}\\p{Ll}+|i|of|and|the)){0,5}$").IsMatch(address.Country)) { yield return new ValidationResult("Country is invalid", [nameof(address.Country)]); } @@ -48,7 +48,7 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("Street is too long", [nameof(address.Street)]); } - if (new Regex("^[\\p{L}\\d]+(?:(\\s)\\p{L}+)*(\\s(?:(\\d+\\p{L}?(/\\d*\\p{L}?)?)))?$").IsMatch(address.Street) is false) + if (!new Regex("^[\\p{L}\\d]+(?:(\\s)\\p{L}+)*(\\s(?:(\\d+\\p{L}?(/\\d*\\p{L}?)?)))?$").IsMatch(address.Street)) { yield return new ValidationResult("Street is invalid", [nameof(address.Street)]); } @@ -63,7 +63,7 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("State is too long", [nameof(address.State)]); } - if (new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{L}+)*$").IsMatch(address.State) is false) + if (!new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{L}+)*$").IsMatch(address.State)) { yield return new ValidationResult("State is invalid", [nameof(address.State)]); } @@ -75,7 +75,7 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("ZipCode is too long", [nameof(address.ZipCode)]); } - if (new Regex("^[\\p{L}\\d\\s-]{3,}$").IsMatch(address.ZipCode) is false) + if (!new Regex("^[\\p{L}\\d\\s-]{3,}$").IsMatch(address.ZipCode)) { yield return new ValidationResult("ZipCode is invalid", [nameof(address.ZipCode)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs index e4fd2264..54a68c45 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs @@ -1,18 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; -using System.Numerics; namespace ReasnAPI.Validators { - public class CommentValidator : IValidator + public class CommentValidator : IValidator { - public static IEnumerable Validate(Comment comment) + public static IEnumerable Validate(CommentDto comment) { - if (string.IsNullOrWhiteSpace(comment.EventId.ToString())) - { - yield return new ValidationResult("EventId is required", [nameof(comment.EventId)]); - } - if (string.IsNullOrWhiteSpace(comment.Content)) { yield return new ValidationResult("Content is required", [nameof(comment.Content)]); @@ -23,20 +17,10 @@ public static IEnumerable Validate(Comment comment) yield return new ValidationResult("Content is too long", [nameof(comment.Content)]); } - if (string.IsNullOrWhiteSpace(comment.CreatedAt.ToString())) - { - yield return new ValidationResult("CreatedAt is required", [nameof(comment.CreatedAt)]); - } - - if (comment.CreatedAt > DateTime.Now) + if (comment.CreatedAt >= DateTime.Now) { yield return new ValidationResult("CreatedAt is in the future", [nameof(comment.CreatedAt)]); } - - if (string.IsNullOrWhiteSpace(comment.UserId.ToString())) - { - yield return new ValidationResult("UserId is required", [nameof(comment.UserId)]); - } } } } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs index 87de07e9..f86f601c 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class EventValidator : IValidator + public class EventValidator : IValidator { - public static IEnumerable Validate(Event eventData) + public static IEnumerable Validate(EventDto eventData) { if (string.IsNullOrWhiteSpace(eventData.Name)) { @@ -18,11 +18,6 @@ public static IEnumerable Validate(Event eventData) yield return new ValidationResult("Name is too long", [nameof(eventData.Name)]); } - if (string.IsNullOrWhiteSpace(eventData.AddressId.ToString())) - { - yield return new ValidationResult("AddressId is required", [nameof(eventData.AddressId)]); - } - if (string.IsNullOrWhiteSpace(eventData.Description)) { yield return new ValidationResult("Description is required", [nameof(eventData.Description)]); @@ -33,34 +28,19 @@ public static IEnumerable Validate(Event eventData) yield return new ValidationResult("Description is too long", [nameof(eventData.Description)]); } - if (string.IsNullOrWhiteSpace(eventData.OrganizerId.ToString())) - { - yield return new ValidationResult("OrganizerId is required", [nameof(eventData.OrganizerId)]); - } - - if (string.IsNullOrWhiteSpace(eventData.StartAt.ToString())) - { - yield return new ValidationResult("StartTime is required", [nameof(eventData.StartAt)]); - } - - if (string.IsNullOrWhiteSpace(eventData.EndAt.ToString())) - { - yield return new ValidationResult("EndTime is required", [nameof(eventData.EndAt)]); - } - if (eventData.StartAt > eventData.EndAt) { yield return new ValidationResult("StartTime is after EndTime", [nameof(eventData.StartAt)]); } - if (string.IsNullOrWhiteSpace(eventData.CreatedAt.ToString())) + if (eventData.CreatedAt >= DateTime.Now) { - yield return new ValidationResult("CreatedAt is required", [nameof(eventData.CreatedAt)]); + yield return new ValidationResult("CreatedAt is in the future", [nameof(eventData.CreatedAt)]); } - if (string.IsNullOrWhiteSpace(eventData.UpdatedAt.ToString())) + if (eventData.UpdatedAt >= DateTime.Now) { - yield return new ValidationResult("UpdatedAt is required", [nameof(eventData.UpdatedAt)]); + yield return new ValidationResult("UpdatedAt is in the future", [nameof(eventData.UpdatedAt)]); } if (string.IsNullOrWhiteSpace(eventData.Slug)) @@ -73,15 +53,10 @@ public static IEnumerable Validate(Event eventData) yield return new ValidationResult("Slug is too long", [nameof(eventData.Slug)]); } - if (new Regex("^[\\p{L}\\d]+[\\p{L}\\d-]*$").IsMatch(eventData.Slug)) + if (!new Regex("^[\\p{L}\\d]+[\\p{L}\\d-]*$").IsMatch(eventData.Slug)) { yield return new ValidationResult("Slug is invalid", [nameof(eventData.Name)]); } - - if (string.IsNullOrWhiteSpace(eventData.StatusId.ToString())) - { - yield return new ValidationResult("StatusId is required", [nameof(eventData.StatusId)]); - } } } } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs deleted file mode 100644 index 15de2bfc..00000000 --- a/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs +++ /dev/null @@ -1,21 +0,0 @@ -using ReasnAPI.Models.Database; -using System.ComponentModel.DataAnnotations; - -namespace ReasnAPI.Validators -{ - public class ImageValidator : IValidator - { - public static IEnumerable Validate(Image image) - { - if (string.IsNullOrWhiteSpace(image.ObjectTypeId.ToString())) - { - yield return new ValidationResult("ObjectTypeId is required", [nameof(image.ObjectTypeId)]); - } - - if (string.IsNullOrWhiteSpace(image.ObjectId.ToString())) - { - yield return new ValidationResult("ObjectId is required", [nameof(image.ObjectId)]); - } - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs index ce4704ed..d6068f0b 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class InterestValidator : IValidator + public class InterestValidator : IValidator { - public static IEnumerable Validate(Interest interest) + public static IEnumerable Validate(IntrestDto interest) { if (string.IsNullOrWhiteSpace(interest.Name)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(Interest interest) yield return new ValidationResult("Name is too long", [nameof(interest.Name)]); } - if (new Regex("^\\p{Lu}\\p{Ll}+(?:\\s\\p{L}+)*$").IsMatch(interest.Name)) + if (!new Regex("^\\p{Lu}\\p{Ll}+(?:\\s\\p{L}+)*$").IsMatch(interest.Name)) { yield return new ValidationResult("Name is invalid", [nameof(interest.Name)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs index c26bddaf..e2e965ce 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs @@ -18,7 +18,7 @@ public static IEnumerable Validate(ObjectType objectType) yield return new ValidationResult("Name is too long", [nameof(objectType.Name)]); } - if (new Regex("^(Event|User)$").IsMatch(objectType.Name) is false) + if (!new Regex("^(Event|User)$").IsMatch(objectType.Name)) { yield return new ValidationResult("Name is invalid", [nameof(objectType.Name)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs index 8a06fe21..42ad28fa 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class ParameterValidator : IValidator + public class ParameterValidator : IValidator { - public static IEnumerable Validate(Parameter parameter) + public static IEnumerable Validate(ParameterDto parameter) { if (string.IsNullOrWhiteSpace(parameter.Key)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(Parameter parameter) yield return new ValidationResult("Key is too long", [nameof(parameter.Key)]); } - if (new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(parameter.Key)) + if (!new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(parameter.Key)) { yield return new ValidationResult("Key is invalid", [nameof(parameter.Key)]); } @@ -33,7 +33,7 @@ public static IEnumerable Validate(Parameter parameter) yield return new ValidationResult("Value is too long", [nameof(parameter.Value)]); } - if (new Regex("^[\\p{L}\\d]+(?:\\s[\\p{L}\\d]+)*$").IsMatch(parameter.Value)) + if (!new Regex("^[\\p{L}\\d]+(?:\\s[\\p{L}\\d]+)*$").IsMatch(parameter.Value)) { yield return new ValidationResult("Value is invalid", [nameof(parameter.Value)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs index 362a9fc9..83712151 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs @@ -1,24 +1,19 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class RoleValidator : IValidator + public class RoleValidator : IValidator { - public static IEnumerable Validate(Role role) + public static IEnumerable Validate(RoleDto role) { if (string.IsNullOrWhiteSpace(role.Name)) { yield return new ValidationResult("Role name is required", [nameof(role.Name)]); } - if (role.Name.Length > 32) - { - yield return new ValidationResult("Role name is too long", [nameof(role.Name)]); - } - - if (new Regex("^(Organizer|Admin|User)$").IsMatch(role.Name) is false) + if (!new Regex("^(Organizer|Admin|User)$").IsMatch(role.Name)) { yield return new ValidationResult("Role name is invalid", [nameof(role.Name)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs index a28e7bb1..680a6e0d 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs @@ -1,29 +1,19 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class StatusValidator : IValidator + public class StatusValidator : IValidator { - public static IEnumerable Validate(Status status) + public static IEnumerable Validate(StatusDto status) { if (string.IsNullOrWhiteSpace(status.Name)) { yield return new ValidationResult("Name is required", [nameof(status.Name)]); } - if (status.Name.Length > 32) - { - yield return new ValidationResult("Name is too long", [nameof(status.Name)]); - } - - if (string.IsNullOrWhiteSpace(status.ObjectTypeId.ToString())) - { - yield return new ValidationResult("ObjectTypeId is required", [nameof(status.ObjectTypeId)]); - } - - if (new Regex("^(Interested|Participating|Completed|In progress|Waiting for approval)$").IsMatch(status.Name) is false) + if (!new Regex("^(Interested|Participating|Completed|In progress|Waiting for approval)$").IsMatch(status.Name)) { yield return new ValidationResult("Name is invalid", [nameof(status.Name)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs index ff7ee67c..10c45944 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class TagValidator : IValidator + public class TagValidator : IValidator { - public static IEnumerable Validate(Tag tag) + public static IEnumerable Validate(TagDto tag) { if (string.IsNullOrWhiteSpace(tag.Name)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(Tag tag) yield return new ValidationResult("Name is too long", [nameof(tag.Name)]); } - if (new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(tag.Name)) + if (!new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(tag.Name)) { yield return new ValidationResult("Name is invalid", [nameof(tag.Name)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs index b6dfb0d0..2e153655 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class UserValidator : IValidator + public class UserValidator : IValidator { - public static IEnumerable Validate(User user) + public static IEnumerable Validate(UserDto user) { if (string.IsNullOrWhiteSpace(user.Name)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(User user) yield return new ValidationResult("Name is too long", [nameof(user.Name)]); } - if (new Regex("^\\p{Lu}\\p{Ll}+$").IsMatch(user.Name) is false) + if (!new Regex("^\\p{Lu}\\p{Ll}+$").IsMatch(user.Name)) { yield return new ValidationResult("Name is invalid", [nameof(user.Name)]); } @@ -33,7 +33,7 @@ public static IEnumerable Validate(User user) yield return new ValidationResult("Surname is too long", [nameof(user.Surname)]); } - if (new Regex("^\\p{L}+(?:[\\s'-]?\\p{L}+)*$").IsMatch(user.Surname) is false) + if (!new Regex("^\\p{L}+(?:[\\s'-]?\\p{L}+)*$").IsMatch(user.Surname)) { yield return new ValidationResult("Surname is invalid", [nameof(user.Surname)]); } @@ -48,31 +48,11 @@ public static IEnumerable Validate(User user) yield return new ValidationResult("Username is too long", [nameof(user.Username)]); } - if (new Regex("^[\\p{L}\\d._%+-]+$").IsMatch(user.Username) is false) + if (!new Regex("^[\\p{L}\\d._%+-]+$").IsMatch(user.Username)) { yield return new ValidationResult("Username is invalid", [nameof(user.Username)]); } - if (string.IsNullOrWhiteSpace(user.Password)) - { - yield return new ValidationResult("Password is required", [nameof(user.Password)]); - } - - if (string.IsNullOrWhiteSpace(user.CreatedAt.ToString())) - { - yield return new ValidationResult("CreatedAt is required", [nameof(user.CreatedAt)]); - } - - if (string.IsNullOrWhiteSpace(user.UpdatedAt.ToString())) - { - yield return new ValidationResult("UpdatedAt is required", [nameof(user.UpdatedAt)]); - } - - if (string.IsNullOrWhiteSpace(user.RoleId.ToString())) - { - yield return new ValidationResult("RoleId is required", [nameof(user.RoleId)]); - } - if (string.IsNullOrWhiteSpace(user.Email)) { yield return new ValidationResult("Email is required", [nameof(user.Email)]); @@ -83,24 +63,19 @@ public static IEnumerable Validate(User user) yield return new ValidationResult("Email is too long", [nameof(user.Email)]); } - if (new Regex("^[a-zA-Z\\d._%+-]+@[a-zA-Z\\d.-]+\\.[a-zA-Z]{2,6}$").IsMatch(user.Email) is false) + if (!new Regex("^[a-zA-Z\\d._%+-]+@[a-zA-Z\\d.-]+\\.[a-zA-Z]{2,6}$").IsMatch(user.Email)) { yield return new ValidationResult("Email is invalid", [nameof(user.Email)]); } - if (string.IsNullOrWhiteSpace(user.AddressId.ToString())) - { - yield return new ValidationResult("AddressId is required", [nameof(user.AddressId)]); - } - if (!string.IsNullOrWhiteSpace(user.Phone)) { - if (!string.IsNullOrWhiteSpace(user.Phone) && user.Phone.Length > 16) + if (user.Phone.Length > 16) { yield return new ValidationResult("Phone is too long", [nameof(user.Phone)]); } - if (new Regex("^\\+\\d{1,3}\\s\\d{1,15}$").IsMatch(user.Phone) is false) + if (!new Regex("^\\+\\d{1,3}\\s\\d{1,15}$").IsMatch(user.Phone)) { yield return new ValidationResult("Phone is invalid", [nameof(user.Phone)]); } From 0ac564d5de6edffd4b230741a352731e51521795 Mon Sep 17 00:00:00 2001 From: Maciej Koperdowski Date: Mon, 13 May 2024 19:57:30 +0200 Subject: [PATCH 13/24] Revert "Added regex in validators, changed models into dtos, created unit tests" This reverts commit b2825e863a91296d5906b3b2bbaf0c7eb927a5db. --- .../ReasnAPI.Tests/ReasnAPI.Tests.csproj | 4 - Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs | 12 + .../Validators/AddressValidatorTests.cs | 336 ---------------- .../Validators/CommentValidatorTests.cs | 65 --- .../Validators/EventValidatorTests.cs | 257 ------------ .../Validators/InterestValidatorTests.cs | 62 --- .../Validators/ObjectTypeValidatorTests.cs | 75 ---- .../Validators/ParameterValidatorTests.cs | 109 ----- .../Validators/RoleValidatorTests.cs | 75 ---- .../Validators/StatusValidatorTests.cs | 101 ----- .../Validators/TagValidatorTests.cs | 62 --- .../Validators/UserValidatorTests.cs | 374 ------------------ Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj | 1 + .../ReasnAPI/Validators/AddressValidator.cs | 16 +- .../ReasnAPI/Validators/CommentValidator.cs | 24 +- .../ReasnAPI/Validators/EventValidator.cs | 41 +- .../ReasnAPI/Validators/ImageValidator.cs | 21 + .../ReasnAPI/Validators/InterestValidator.cs | 8 +- .../Validators/ObjectTypeValidator.cs | 2 +- .../ReasnAPI/Validators/ParameterValidator.cs | 10 +- .../ReasnAPI/Validators/RoleValidator.cs | 13 +- .../ReasnAPI/Validators/StatusValidator.cs | 18 +- .../ReasnAPI/Validators/TagValidator.cs | 8 +- .../ReasnAPI/Validators/UserValidator.cs | 43 +- 24 files changed, 166 insertions(+), 1571 deletions(-) create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/AddressValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs diff --git a/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj b/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj index 44463a72..1b46a3ed 100644 --- a/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj +++ b/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj @@ -17,10 +17,6 @@ - - - - diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs new file mode 100644 index 00000000..46dac6f2 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs @@ -0,0 +1,12 @@ +namespace ReasnAPI.Tests +{ + [TestClass] + public class UnitTest1 + { + [TestMethod] + public void TestAdd() + { + Assert.AreEqual(17, 17); + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/AddressValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/AddressValidatorTests.cs deleted file mode 100644 index 0ff447ab..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/AddressValidatorTests.cs +++ /dev/null @@ -1,336 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class AddressValidatorTests - { - [TestMethod] - public void Validate_WhenCityIsEmpty_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "", - Country = "Country", - Street = "Street", - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "City is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "City is invalid")); - } - - [TestMethod] - public void Validate_WhenCityIsTooLong_ReturnsValidationResult() - { - var address = new AddressDto - { - City = new string('a', 65), - Country = "Country", - Street = "Street", - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "City is too long")); - } - - [TestMethod] - public void Validate_WhenCityIsInvalid_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "Invalid City", - Country = "Country", - Street = "Street", - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "City is invalid")); - } - - [TestMethod] - public void Validate_WhenCityIsValid_ReturnsNoValidationResult() - { - var address = new AddressDto - { - City = "Valid City", - Country = "Country", - Street = "Street", - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenCountryIsEmpty_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "", - Street = "Street", - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Country is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Country is invalid")); - } - - [TestMethod] - public void Validate_WhenCountryIsTooLong_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = new string('a', 65), - Street = "Street", - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Country is too long")); - } - - [TestMethod] - public void Validate_WhenCountryIsInvalid_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Invalid Country", - Street = "Street", - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Country is invalid")); - } - - [TestMethod] - public void Validate_WhenCountryIsValid_ReturnsNoValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Valid Country", - Street = "Street", - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenStreetIsEmpty_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Country", - Street = "", - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Street is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Street is invalid")); - } - - [TestMethod] - public void Validate_WhenStreetIsTooLong_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Country", - Street = new string('a', 65), - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Street is too long")); - } - - [TestMethod] - public void Validate_WhenStreetIsInvalid_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Country", - Street = "Invalid Street", - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Street is invalid")); - } - - [TestMethod] - public void Validate_WhenStreetIsValid_ReturnsNoValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Country", - Street = "Valid Street", - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenStateIsEmpty_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Country", - Street = "Street", - State = "", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "State is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "State is invalid")); - } - - [TestMethod] - public void Validate_WhenStateIsTooLong_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Country", - Street = "Street", - State = new string('a', 65), - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "State is too long")); - } - - [TestMethod] - public void Validate_WhenStateIsInvalid_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Country", - Street = "Street", - State = "Invalid State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "State is invalid")); - } - - [TestMethod] - public void Validate_WhenStateIsValid_ReturnsNoValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Country", - Street = "Street", - State = "Valid State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Valdate_WhenZipCodeIsTooLong_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Country", - Street = "Street", - State = "State", - ZipCode = new string('0', 9) - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "ZipCode is too long")); - } - - [TestMethod] - public void Validate_WhenZipCodeIsInvalid_ReturnsValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Country", - Street = "Street", - State = "State", - ZipCode = "Invalid_" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "ZipCode is invalid")); - } - - [TestMethod] - public void Validate_WhenZipCodeIsValid_ReturnsNoValidationResult() - { - var address = new AddressDto - { - City = "City", - Country = "Country", - Street = "Street", - State = "State", - ZipCode = "00-000" - }; - - var result = AddressValidator.Validate(address); - - Assert.IsFalse(result.Any()); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs deleted file mode 100644 index 49f64da6..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs +++ /dev/null @@ -1,65 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class CommentValidatorTests - { - [TestMethod] - public void Validate_WhenContentIsEmpty_ReturnsValidationResult() - { - var comment = new CommentDto - { - Content = "", - CreatedAt = DateTime.Now - }; - - var result = CommentValidator.Validate(comment); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Content is required")); - } - - [TestMethod] - public void Validate_WhenContentIsTooLong_ReturnsValidationResult() - { - var comment = new CommentDto - { - Content = new string('a', 1025), - CreatedAt = DateTime.Now - }; - - var result = CommentValidator.Validate(comment); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Content is too long")); - } - - [TestMethod] - public void Validate_WhenCreatedAtIsInTheFuture_ReturnsValidationResult() - { - var comment = new CommentDto - { - Content = "Content", - CreatedAt = DateTime.Now.AddMinutes(1) - }; - - var result = CommentValidator.Validate(comment); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "CreatedAt is in the future")); - } - - [TestMethod] - public void Validate_WhenCommentIsValid_ReturnsNoValidationResult() - { - var comment = new CommentDto - { - Content = "Content", - CreatedAt = DateTime.Now - }; - - var result = CommentValidator.Validate(comment); - - Assert.IsFalse(result.Any()); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs deleted file mode 100644 index ce6b68ff..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs +++ /dev/null @@ -1,257 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class EventValidatorTests - { - [TestMethod] - public void Validate_WhenNameIsEmpty_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "", - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "slug" - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); - } - - [TestMethod] - public void Validate_WhenNameIsTooLong_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = new string('a', 65), - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "slug" - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); - } - - [TestMethod] - public void Validate_WhenNameIsValid_ReturnsNoValidationResult() - { - var event1 = new EventDto - { - Name = "ValidName", - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "slug" - }; - - var result = EventValidator.Validate(event1); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenDescriptionIsEmpty_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "", - StartAt = DateTime.Now, - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "slug" - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Description is required")); - } - - [TestMethod] - public void Validate_WhenDescriptionIsTooLong_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = new string('a', 4049), - StartAt = DateTime.Now, - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "slug" - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Description is too long")); - } - - [TestMethod] - public void Validate_WhenDescriptionIsValid_ReturnsNoValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "Valid Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "slug" - }; - - var result = EventValidator.Validate(event1); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenStartAtIsAfterEndAt_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "Description", - StartAt = DateTime.Now.AddMinutes(1), - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "slug" - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "StartTime is after EndTime")); - } - - [TestMethod] - public void Validate_WhenCreatedAtIsInTheFuture_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now, - CreatedAt = DateTime.Now.AddMinutes(1), - UpdatedAt = DateTime.Now, - Slug = "slug" - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "CreatedAt is in the future")); - } - - [TestMethod] - public void Validate_WhenUpdatedAtIsInTheFuture_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now.AddMinutes(1), - Slug = "slug" - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "UpdatedAt is in the future")); - } - - [TestMethod] - public void Validate_WhenSlugIsEmpty_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "" - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is invalid")); - } - - [TestMethod] - public void Validate_WhenSlugIsTooLong_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = new string('a', 129) - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is too long")); - } - - [TestMethod] - public void Validate_WhenSlugIsIsInvalid_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "invalid slug" - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is invalid")); - } - - [TestMethod] - public void Validate_WhenSlugIsValid_ReturnsNoValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "valid-slug" - }; - - var result = EventValidator.Validate(event1); - - Assert.IsFalse(result.Any()); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs deleted file mode 100644 index 4d64732a..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs +++ /dev/null @@ -1,62 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class InterestValidatorTests - { - [TestMethod] - public void Validate_WhenNameIsEmpty_ReturnsValidationResult() - { - var interest = new IntrestDto - { - Name = "" - }; - - var result = InterestValidator.Validate(interest); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsTooLong_ReturnsValidationResult() - { - var interest = new IntrestDto - { - Name = new string('a', 33) - }; - - var result = InterestValidator.Validate(interest); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); - } - - [TestMethod] - public void Validate_WhenNameIsInvalid_ReturnsValidationResult() - { - var interest = new IntrestDto - { - Name = "Invalid Name" - }; - - var result = InterestValidator.Validate(interest); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsValid_ReturnsNoValidationResult() - { - var interest = new IntrestDto - { - Name = "Valid Name" - }; - - var result = InterestValidator.Validate(interest); - - Assert.IsFalse(result.Any()); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs deleted file mode 100644 index 5c1480ee..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs +++ /dev/null @@ -1,75 +0,0 @@ -using ReasnAPI.Models.Database; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class ObjectTypeValidatorTests - { - [TestMethod] - public void Validate_WhenNameIsEmpty_ReturnsValidationResult() - { - var objectType = new ObjectType - { - Name = "" - }; - - var result = ObjectTypeValidator.Validate(objectType); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsTooLong_ReturnsValidationResult() - { - var objectType = new ObjectType - { - Name = new string('a', 33) - }; - - var result = ObjectTypeValidator.Validate(objectType); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); - } - - [TestMethod] - public void Validate_WhenNameIsInvalid_ReturnsValidationResult() - { - var objectType = new ObjectType - { - Name = "Invalid Name" - }; - - var result = ObjectTypeValidator.Validate(objectType); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsEvent_ReturnsNoValidationResult() - { - var objectType = new ObjectType - { - Name = "Event" - }; - - var result = ObjectTypeValidator.Validate(objectType); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenNameIsUser_ReturnsNoValidationResult() - { - var objectType = new ObjectType - { - Name = "User" - }; - - var result = ObjectTypeValidator.Validate(objectType); - - Assert.IsFalse(result.Any()); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs deleted file mode 100644 index 424f987b..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs +++ /dev/null @@ -1,109 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class ParameterValidatorTests - { - [TestMethod] - public void Validate_WhenKeyIsEmpty_ReturnsKeyIsRequired() - { - var parameter = new ParameterDto - { - Key = "", - Value = "value" - }; - - var result = ParameterValidator.Validate(parameter); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is invalid")); - } - - [TestMethod] - public void Validate_WhenKeyIsTooLong_ReturnsKeyIsTooLong() - { - var parameter = new ParameterDto - { - Key = new string('a', 33), - Value = "value" - }; - - var result = ParameterValidator.Validate(parameter); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is too long")); - } - - [TestMethod] - public void Validate_WhenKeyIsInvalid_ReturnsKeyIsInvalid() - { - var parameter = new ParameterDto - { - Key = "Invalid Key", - Value = "value" - }; - - var result = ParameterValidator.Validate(parameter); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is invalid")); - } - - [TestMethod] - public void Validate_WhenValueIsEmpty_ReturnsValueIsRequired() - { - var parameter = new ParameterDto - { - Key = "key", - Value = "" - }; - - var result = ParameterValidator.Validate(parameter); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is invalid")); - } - - [TestMethod] - public void Validate_WhenValueIsTooLong_ReturnsValueIsTooLong() - { - var parameter = new ParameterDto - { - Key = "key", - Value = new string('a', 65) - }; - - var result = ParameterValidator.Validate(parameter); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is too long")); - } - - [TestMethod] - public void Validate_WhenValueIsInvalid_ReturnsValueIsInvalid() - { - var parameter = new ParameterDto - { - Key = "key", - Value = "Invalid Value" - }; - - var result = ParameterValidator.Validate(parameter); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is invalid")); - } - - [TestMethod] - public void Validate_WhenValueAndKeyAreValid_ReturnsNoValidationResult() - { - var parameter = new ParameterDto - { - Key = "key", - Value = "value" - }; - - var result = ParameterValidator.Validate(parameter); - - Assert.IsFalse(result.Any()); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs deleted file mode 100644 index a662254a..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs +++ /dev/null @@ -1,75 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class RoleValidatorTests - { - [TestMethod] - public void Validate_WhenRoleNameIsEmpty_ReturnsValidationResult() - { - var role = new RoleDto - { - Name = "" - }; - - var result = RoleValidator.Validate(role); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Role name is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Role name is invalid")); - } - - [TestMethod] - public void Validate_WhenRoleNameIsInvalid_ReturnsValidationResult() - { - var role = new RoleDto - { - Name = "Invalid Role" - }; - - var result = RoleValidator.Validate(role); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Role name is invalid")); - } - - [TestMethod] - public void Validate_WhenRoleNameIsOrganizer_ReturnsNoValidationResult() - { - var role = new RoleDto - { - Name = "Organizer" - }; - - var result = RoleValidator.Validate(role); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenRoleNameIsAdmin_ReturnsNoValidationResult() - { - var role = new RoleDto - { - Name = "Admin" - }; - - var result = RoleValidator.Validate(role); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenRoleNameIsUser_ReturnsNoValidationResult() - { - var role = new RoleDto - { - Name = "User" - }; - - var result = RoleValidator.Validate(role); - - Assert.IsFalse(result.Any()); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs deleted file mode 100644 index c3438cdf..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs +++ /dev/null @@ -1,101 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class StatusValidatorTests - { - [TestMethod] - public void Validate_WhenNameIsEmpty_ReturnsValidationResult() - { - var status = new StatusDto - { - Name = "" - }; - - var result = StatusValidator.Validate(status); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsInvalid_ReturnsValidationResult() - { - var status = new StatusDto - { - Name = "Invalid Name" - }; - - var result = StatusValidator.Validate(status); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsInterested_ReturnsValidationResult() - { - var status = new StatusDto - { - Name = "Interested" - }; - - var result = StatusValidator.Validate(status); - - Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsParticipating_ReturnsValidationResult() - { - var status = new StatusDto - { - Name = "Participating" - }; - - var result = StatusValidator.Validate(status); - - Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsCompleted_ReturnsValidationResult() - { - var status = new StatusDto - { - Name = "Completed" - }; - - var result = StatusValidator.Validate(status); - - Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsInProgress_ReturnsValidationResult() - { - var status = new StatusDto - { - Name = "In progress" - }; - - var result = StatusValidator.Validate(status); - - Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsWaitingForApproval_ReturnsValidationResult() - { - var status = new StatusDto - { - Name = "Waiting for approval" - }; - - var result = StatusValidator.Validate(status); - - Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs deleted file mode 100644 index 4a935bdd..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs +++ /dev/null @@ -1,62 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class TagValidatorTests - { - [TestMethod] - public void Validate_WhenNameIsEmpty_ReturnsValidationResult() - { - var tag = new TagDto - { - Name = "" - }; - - var result = TagValidator.Validate(tag); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsTooLong_ReturnsValidationResult() - { - var tag = new TagDto - { - Name = new string('a', 65) - }; - - var result = TagValidator.Validate(tag); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); - } - - [TestMethod] - public void Validate_WhenNameIsInvalid_ReturnsValidationResult() - { - var tag = new TagDto - { - Name = "Invalid Name" - }; - - var result = TagValidator.Validate(tag); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsValid_ReturnsValidationResult() - { - var tag = new TagDto - { - Name = "Valid Name" - }; - - var result = TagValidator.Validate(tag); - - Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs deleted file mode 100644 index a5de2ecf..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs +++ /dev/null @@ -1,374 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class UserValidatorTests - { - [TestMethod] - public void Validate_WhenNameIsEmpty_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "", - Surname = "Surname", - Username = "Username", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsTooLong_ReturnsValidationResult() - { - var user = new UserDto - { - Name = new string('a', 65), - Surname = "Surname", - Username = "Username", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); - } - - [TestMethod] - public void Validate_WhenNameIsInvalid_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Invalid Name", - Surname = "Surname", - Username = "Username", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsValid_ReturnsNoValidationResult() - { - var user = new UserDto - { - Name = "Validname", - Surname = "Surname", - Username = "Username", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenSurnameIsEmpty_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "", - Username = "Username", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is invalid")); - } - - [TestMethod] - public void Validate_WhenSurnameIsTooLong_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = new string('a', 65), - Username = "Username", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is too long")); - } - - [TestMethod] - public void Validate_WhenSurnameIsInvalid_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Invalid Surname", - Username = "Username", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is invalid")); - } - - [TestMethod] - public void Validate_WhenSurnameIsValid_ReturnsNoValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Validsurname", - Username = "Username", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenUsernameIsEmpty_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is invalid")); - } - - [TestMethod] - public void Validate_WhenUsernameIsTooLong_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = new string('a', 65), - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is too long")); - } - - [TestMethod] - public void Validate_WhenUsernameIsInvalid_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "Invalid Username", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is invalid")); - } - - [TestMethod] - public void Validate_WhenUsernameIsValid_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "ValidUsername", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenEmailIsEmpty_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "Username", - RoleId = 1, - Email = "", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is invalid")); - } - - [TestMethod] - public void Validate_WhenEmailIsTooLong_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "Username", - RoleId = 1, - Email = new string('a', 256), - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is too long")); - } - - [TestMethod] - public void Validate_WhenEmailIsInvalid_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "Username", - RoleId = 1, - Email = "Invalid Email", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is invalid")); - } - - [TestMethod] - public void Validate_WhenEmailIsValid_ReturnsNoValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "Username", - RoleId = 1, - Email = "valid@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenPhoneIsTooLong_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "Username", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = new string('a', 20) - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Phone is too long")); - } - - [TestMethod] - public void Validate_WhenPhoneIsInvalid_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "Username", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "Invalid Phone" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Phone is invalid")); - } - - [TestMethod] - public void Validate_WhenPhoneIsValid_ReturnsNoValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "Username", - RoleId = 1, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsFalse(result.Any()); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj b/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj index a5564cb9..02ce3550 100644 --- a/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj +++ b/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj @@ -23,6 +23,7 @@ + diff --git a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs index e6c9897c..08aa4c60 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.DTOs; +using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class AddressValidator : IValidator + public class AddressValidator : IValidator
{ - public static IEnumerable Validate(AddressDto address) + public static IEnumerable Validate(Address address) { if (string.IsNullOrWhiteSpace(address.City)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(AddressDto address) yield return new ValidationResult("City is too long", [nameof(address.City)]); } - if (!new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{Lu}\\p{Ll}+)*$").IsMatch(address.City)) + if (new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{Lu}\\p{Ll}+)*$").IsMatch(address.City) is false) { yield return new ValidationResult("City is invalid", [nameof(address.City)]); } @@ -33,7 +33,7 @@ public static IEnumerable Validate(AddressDto address) yield return new ValidationResult("Country is too long", [nameof(address.Country)]); } - if (!new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)(\\p{Lu}\\p{Ll}+|i|of|and|the)){0,5}$").IsMatch(address.Country)) + if (new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)(\\p{Lu}\\p{Ll}+|i|of|and|the)){0,5}$").IsMatch(address.Country) is false) { yield return new ValidationResult("Country is invalid", [nameof(address.Country)]); } @@ -48,7 +48,7 @@ public static IEnumerable Validate(AddressDto address) yield return new ValidationResult("Street is too long", [nameof(address.Street)]); } - if (!new Regex("^[\\p{L}\\d]+(?:(\\s)\\p{L}+)*(\\s(?:(\\d+\\p{L}?(/\\d*\\p{L}?)?)))?$").IsMatch(address.Street)) + if (new Regex("^[\\p{L}\\d]+(?:(\\s)\\p{L}+)*(\\s(?:(\\d+\\p{L}?(/\\d*\\p{L}?)?)))?$").IsMatch(address.Street) is false) { yield return new ValidationResult("Street is invalid", [nameof(address.Street)]); } @@ -63,7 +63,7 @@ public static IEnumerable Validate(AddressDto address) yield return new ValidationResult("State is too long", [nameof(address.State)]); } - if (!new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{L}+)*$").IsMatch(address.State)) + if (new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{L}+)*$").IsMatch(address.State) is false) { yield return new ValidationResult("State is invalid", [nameof(address.State)]); } @@ -75,7 +75,7 @@ public static IEnumerable Validate(AddressDto address) yield return new ValidationResult("ZipCode is too long", [nameof(address.ZipCode)]); } - if (!new Regex("^[\\p{L}\\d\\s-]{3,}$").IsMatch(address.ZipCode)) + if (new Regex("^[\\p{L}\\d\\s-]{3,}$").IsMatch(address.ZipCode) is false) { yield return new ValidationResult("ZipCode is invalid", [nameof(address.ZipCode)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs index 54a68c45..e4fd2264 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs @@ -1,12 +1,18 @@ -using ReasnAPI.Models.DTOs; +using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; +using System.Numerics; namespace ReasnAPI.Validators { - public class CommentValidator : IValidator + public class CommentValidator : IValidator { - public static IEnumerable Validate(CommentDto comment) + public static IEnumerable Validate(Comment comment) { + if (string.IsNullOrWhiteSpace(comment.EventId.ToString())) + { + yield return new ValidationResult("EventId is required", [nameof(comment.EventId)]); + } + if (string.IsNullOrWhiteSpace(comment.Content)) { yield return new ValidationResult("Content is required", [nameof(comment.Content)]); @@ -17,10 +23,20 @@ public static IEnumerable Validate(CommentDto comment) yield return new ValidationResult("Content is too long", [nameof(comment.Content)]); } - if (comment.CreatedAt >= DateTime.Now) + if (string.IsNullOrWhiteSpace(comment.CreatedAt.ToString())) + { + yield return new ValidationResult("CreatedAt is required", [nameof(comment.CreatedAt)]); + } + + if (comment.CreatedAt > DateTime.Now) { yield return new ValidationResult("CreatedAt is in the future", [nameof(comment.CreatedAt)]); } + + if (string.IsNullOrWhiteSpace(comment.UserId.ToString())) + { + yield return new ValidationResult("UserId is required", [nameof(comment.UserId)]); + } } } } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs index f86f601c..87de07e9 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.DTOs; +using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class EventValidator : IValidator + public class EventValidator : IValidator { - public static IEnumerable Validate(EventDto eventData) + public static IEnumerable Validate(Event eventData) { if (string.IsNullOrWhiteSpace(eventData.Name)) { @@ -18,6 +18,11 @@ public static IEnumerable Validate(EventDto eventData) yield return new ValidationResult("Name is too long", [nameof(eventData.Name)]); } + if (string.IsNullOrWhiteSpace(eventData.AddressId.ToString())) + { + yield return new ValidationResult("AddressId is required", [nameof(eventData.AddressId)]); + } + if (string.IsNullOrWhiteSpace(eventData.Description)) { yield return new ValidationResult("Description is required", [nameof(eventData.Description)]); @@ -28,19 +33,34 @@ public static IEnumerable Validate(EventDto eventData) yield return new ValidationResult("Description is too long", [nameof(eventData.Description)]); } + if (string.IsNullOrWhiteSpace(eventData.OrganizerId.ToString())) + { + yield return new ValidationResult("OrganizerId is required", [nameof(eventData.OrganizerId)]); + } + + if (string.IsNullOrWhiteSpace(eventData.StartAt.ToString())) + { + yield return new ValidationResult("StartTime is required", [nameof(eventData.StartAt)]); + } + + if (string.IsNullOrWhiteSpace(eventData.EndAt.ToString())) + { + yield return new ValidationResult("EndTime is required", [nameof(eventData.EndAt)]); + } + if (eventData.StartAt > eventData.EndAt) { yield return new ValidationResult("StartTime is after EndTime", [nameof(eventData.StartAt)]); } - if (eventData.CreatedAt >= DateTime.Now) + if (string.IsNullOrWhiteSpace(eventData.CreatedAt.ToString())) { - yield return new ValidationResult("CreatedAt is in the future", [nameof(eventData.CreatedAt)]); + yield return new ValidationResult("CreatedAt is required", [nameof(eventData.CreatedAt)]); } - if (eventData.UpdatedAt >= DateTime.Now) + if (string.IsNullOrWhiteSpace(eventData.UpdatedAt.ToString())) { - yield return new ValidationResult("UpdatedAt is in the future", [nameof(eventData.UpdatedAt)]); + yield return new ValidationResult("UpdatedAt is required", [nameof(eventData.UpdatedAt)]); } if (string.IsNullOrWhiteSpace(eventData.Slug)) @@ -53,10 +73,15 @@ public static IEnumerable Validate(EventDto eventData) yield return new ValidationResult("Slug is too long", [nameof(eventData.Slug)]); } - if (!new Regex("^[\\p{L}\\d]+[\\p{L}\\d-]*$").IsMatch(eventData.Slug)) + if (new Regex("^[\\p{L}\\d]+[\\p{L}\\d-]*$").IsMatch(eventData.Slug)) { yield return new ValidationResult("Slug is invalid", [nameof(eventData.Name)]); } + + if (string.IsNullOrWhiteSpace(eventData.StatusId.ToString())) + { + yield return new ValidationResult("StatusId is required", [nameof(eventData.StatusId)]); + } } } } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs new file mode 100644 index 00000000..15de2bfc --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs @@ -0,0 +1,21 @@ +using ReasnAPI.Models.Database; +using System.ComponentModel.DataAnnotations; + +namespace ReasnAPI.Validators +{ + public class ImageValidator : IValidator + { + public static IEnumerable Validate(Image image) + { + if (string.IsNullOrWhiteSpace(image.ObjectTypeId.ToString())) + { + yield return new ValidationResult("ObjectTypeId is required", [nameof(image.ObjectTypeId)]); + } + + if (string.IsNullOrWhiteSpace(image.ObjectId.ToString())) + { + yield return new ValidationResult("ObjectId is required", [nameof(image.ObjectId)]); + } + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs index d6068f0b..ce4704ed 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.DTOs; +using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class InterestValidator : IValidator + public class InterestValidator : IValidator { - public static IEnumerable Validate(IntrestDto interest) + public static IEnumerable Validate(Interest interest) { if (string.IsNullOrWhiteSpace(interest.Name)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(IntrestDto interest) yield return new ValidationResult("Name is too long", [nameof(interest.Name)]); } - if (!new Regex("^\\p{Lu}\\p{Ll}+(?:\\s\\p{L}+)*$").IsMatch(interest.Name)) + if (new Regex("^\\p{Lu}\\p{Ll}+(?:\\s\\p{L}+)*$").IsMatch(interest.Name)) { yield return new ValidationResult("Name is invalid", [nameof(interest.Name)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs index e2e965ce..c26bddaf 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs @@ -18,7 +18,7 @@ public static IEnumerable Validate(ObjectType objectType) yield return new ValidationResult("Name is too long", [nameof(objectType.Name)]); } - if (!new Regex("^(Event|User)$").IsMatch(objectType.Name)) + if (new Regex("^(Event|User)$").IsMatch(objectType.Name) is false) { yield return new ValidationResult("Name is invalid", [nameof(objectType.Name)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs index 42ad28fa..8a06fe21 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.DTOs; +using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class ParameterValidator : IValidator + public class ParameterValidator : IValidator { - public static IEnumerable Validate(ParameterDto parameter) + public static IEnumerable Validate(Parameter parameter) { if (string.IsNullOrWhiteSpace(parameter.Key)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(ParameterDto parameter) yield return new ValidationResult("Key is too long", [nameof(parameter.Key)]); } - if (!new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(parameter.Key)) + if (new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(parameter.Key)) { yield return new ValidationResult("Key is invalid", [nameof(parameter.Key)]); } @@ -33,7 +33,7 @@ public static IEnumerable Validate(ParameterDto parameter) yield return new ValidationResult("Value is too long", [nameof(parameter.Value)]); } - if (!new Regex("^[\\p{L}\\d]+(?:\\s[\\p{L}\\d]+)*$").IsMatch(parameter.Value)) + if (new Regex("^[\\p{L}\\d]+(?:\\s[\\p{L}\\d]+)*$").IsMatch(parameter.Value)) { yield return new ValidationResult("Value is invalid", [nameof(parameter.Value)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs index 83712151..362a9fc9 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs @@ -1,19 +1,24 @@ -using ReasnAPI.Models.DTOs; +using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class RoleValidator : IValidator + public class RoleValidator : IValidator { - public static IEnumerable Validate(RoleDto role) + public static IEnumerable Validate(Role role) { if (string.IsNullOrWhiteSpace(role.Name)) { yield return new ValidationResult("Role name is required", [nameof(role.Name)]); } - if (!new Regex("^(Organizer|Admin|User)$").IsMatch(role.Name)) + if (role.Name.Length > 32) + { + yield return new ValidationResult("Role name is too long", [nameof(role.Name)]); + } + + if (new Regex("^(Organizer|Admin|User)$").IsMatch(role.Name) is false) { yield return new ValidationResult("Role name is invalid", [nameof(role.Name)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs index 680a6e0d..a28e7bb1 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs @@ -1,19 +1,29 @@ -using ReasnAPI.Models.DTOs; +using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class StatusValidator : IValidator + public class StatusValidator : IValidator { - public static IEnumerable Validate(StatusDto status) + public static IEnumerable Validate(Status status) { if (string.IsNullOrWhiteSpace(status.Name)) { yield return new ValidationResult("Name is required", [nameof(status.Name)]); } - if (!new Regex("^(Interested|Participating|Completed|In progress|Waiting for approval)$").IsMatch(status.Name)) + if (status.Name.Length > 32) + { + yield return new ValidationResult("Name is too long", [nameof(status.Name)]); + } + + if (string.IsNullOrWhiteSpace(status.ObjectTypeId.ToString())) + { + yield return new ValidationResult("ObjectTypeId is required", [nameof(status.ObjectTypeId)]); + } + + if (new Regex("^(Interested|Participating|Completed|In progress|Waiting for approval)$").IsMatch(status.Name) is false) { yield return new ValidationResult("Name is invalid", [nameof(status.Name)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs index 10c45944..ff7ee67c 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.DTOs; +using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class TagValidator : IValidator + public class TagValidator : IValidator { - public static IEnumerable Validate(TagDto tag) + public static IEnumerable Validate(Tag tag) { if (string.IsNullOrWhiteSpace(tag.Name)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(TagDto tag) yield return new ValidationResult("Name is too long", [nameof(tag.Name)]); } - if (!new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(tag.Name)) + if (new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(tag.Name)) { yield return new ValidationResult("Name is invalid", [nameof(tag.Name)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs index 2e153655..b6dfb0d0 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.DTOs; +using ReasnAPI.Models.Database; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class UserValidator : IValidator + public class UserValidator : IValidator { - public static IEnumerable Validate(UserDto user) + public static IEnumerable Validate(User user) { if (string.IsNullOrWhiteSpace(user.Name)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(UserDto user) yield return new ValidationResult("Name is too long", [nameof(user.Name)]); } - if (!new Regex("^\\p{Lu}\\p{Ll}+$").IsMatch(user.Name)) + if (new Regex("^\\p{Lu}\\p{Ll}+$").IsMatch(user.Name) is false) { yield return new ValidationResult("Name is invalid", [nameof(user.Name)]); } @@ -33,7 +33,7 @@ public static IEnumerable Validate(UserDto user) yield return new ValidationResult("Surname is too long", [nameof(user.Surname)]); } - if (!new Regex("^\\p{L}+(?:[\\s'-]?\\p{L}+)*$").IsMatch(user.Surname)) + if (new Regex("^\\p{L}+(?:[\\s'-]?\\p{L}+)*$").IsMatch(user.Surname) is false) { yield return new ValidationResult("Surname is invalid", [nameof(user.Surname)]); } @@ -48,11 +48,31 @@ public static IEnumerable Validate(UserDto user) yield return new ValidationResult("Username is too long", [nameof(user.Username)]); } - if (!new Regex("^[\\p{L}\\d._%+-]+$").IsMatch(user.Username)) + if (new Regex("^[\\p{L}\\d._%+-]+$").IsMatch(user.Username) is false) { yield return new ValidationResult("Username is invalid", [nameof(user.Username)]); } + if (string.IsNullOrWhiteSpace(user.Password)) + { + yield return new ValidationResult("Password is required", [nameof(user.Password)]); + } + + if (string.IsNullOrWhiteSpace(user.CreatedAt.ToString())) + { + yield return new ValidationResult("CreatedAt is required", [nameof(user.CreatedAt)]); + } + + if (string.IsNullOrWhiteSpace(user.UpdatedAt.ToString())) + { + yield return new ValidationResult("UpdatedAt is required", [nameof(user.UpdatedAt)]); + } + + if (string.IsNullOrWhiteSpace(user.RoleId.ToString())) + { + yield return new ValidationResult("RoleId is required", [nameof(user.RoleId)]); + } + if (string.IsNullOrWhiteSpace(user.Email)) { yield return new ValidationResult("Email is required", [nameof(user.Email)]); @@ -63,19 +83,24 @@ public static IEnumerable Validate(UserDto user) yield return new ValidationResult("Email is too long", [nameof(user.Email)]); } - if (!new Regex("^[a-zA-Z\\d._%+-]+@[a-zA-Z\\d.-]+\\.[a-zA-Z]{2,6}$").IsMatch(user.Email)) + if (new Regex("^[a-zA-Z\\d._%+-]+@[a-zA-Z\\d.-]+\\.[a-zA-Z]{2,6}$").IsMatch(user.Email) is false) { yield return new ValidationResult("Email is invalid", [nameof(user.Email)]); } + if (string.IsNullOrWhiteSpace(user.AddressId.ToString())) + { + yield return new ValidationResult("AddressId is required", [nameof(user.AddressId)]); + } + if (!string.IsNullOrWhiteSpace(user.Phone)) { - if (user.Phone.Length > 16) + if (!string.IsNullOrWhiteSpace(user.Phone) && user.Phone.Length > 16) { yield return new ValidationResult("Phone is too long", [nameof(user.Phone)]); } - if (!new Regex("^\\+\\d{1,3}\\s\\d{1,15}$").IsMatch(user.Phone)) + if (new Regex("^\\+\\d{1,3}\\s\\d{1,15}$").IsMatch(user.Phone) is false) { yield return new ValidationResult("Phone is invalid", [nameof(user.Phone)]); } From d1e447c22d84ad36cac3e38ac35c06c9c459178f Mon Sep 17 00:00:00 2001 From: Maciej Koperdowski Date: Mon, 13 May 2024 20:46:33 +0200 Subject: [PATCH 14/24] Added tests, changed models in validators into dtos --- .../ReasnAPI.Tests/ReasnAPI.Tests.csproj | 4 + Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs | 12 - .../Validators/AddressValidatorTests.cs | 336 ++++++++++++++++ .../Validators/CommentValidatorTests.cs | 65 +++ .../Validators/EventValidatorTests.cs | 257 ++++++++++++ .../Validators/InterestValidatorTests.cs | 62 +++ .../Validators/ObjectTypeValidatorTests.cs | 62 +++ .../Validators/ParameterValidatorTests.cs | 109 +++++ .../Validators/RoleValidatorTests.cs | 75 ++++ .../Validators/StatusValidatorTests.cs | 101 +++++ .../Validators/TagValidatorTests.cs | 62 +++ .../Validators/UserValidatorTests.cs | 374 ++++++++++++++++++ .../ReasnAPI/Validators/AddressValidator.cs | 18 +- .../ReasnAPI/Validators/CommentValidator.cs | 26 +- .../ReasnAPI/Validators/EventValidator.cs | 43 +- .../ReasnAPI/Validators/ImageValidator.cs | 21 - .../ReasnAPI/Validators/InterestValidator.cs | 10 +- .../Validators/ObjectTypeValidator.cs | 9 +- .../ReasnAPI/Validators/ParameterValidator.cs | 12 +- .../ReasnAPI/Validators/RoleValidator.cs | 15 +- .../ReasnAPI/Validators/StatusValidator.cs | 20 +- .../ReasnAPI/Validators/TagValidator.cs | 10 +- .../ReasnAPI/Validators/UserValidator.cs | 45 +-- 23 files changed, 1568 insertions(+), 180 deletions(-) delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/AddressValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs diff --git a/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj b/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj index 1b46a3ed..44463a72 100644 --- a/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj +++ b/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj @@ -17,6 +17,10 @@ + + + + diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs deleted file mode 100644 index 46dac6f2..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace ReasnAPI.Tests -{ - [TestClass] - public class UnitTest1 - { - [TestMethod] - public void TestAdd() - { - Assert.AreEqual(17, 17); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/AddressValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/AddressValidatorTests.cs new file mode 100644 index 00000000..c3606a75 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/AddressValidatorTests.cs @@ -0,0 +1,336 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class AddressValidatorTests + { + [TestMethod] + public void Validate_WhenCityIsEmpty_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "", + Country = "Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "City is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "City is invalid")); + } + + [TestMethod] + public void Validate_WhenCityIsTooLong_ReturnsValidationResult() + { + var address = new AddressDto + { + City = new string('a', 65), + Country = "Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "City is too long")); + } + + [TestMethod] + public void Validate_WhenCityIsInvalid_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "Invalid City", + Country = "Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "City is invalid")); + } + + [TestMethod] + public void Validate_WhenCityIsValid_ReturnsNoValidationResult() + { + var address = new AddressDto + { + City = "Valid City", + Country = "Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenCountryIsEmpty_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Country is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Country is invalid")); + } + + [TestMethod] + public void Validate_WhenCountryIsTooLong_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = new string('a', 65), + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Country is too long")); + } + + [TestMethod] + public void Validate_WhenCountryIsInvalid_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Invalid Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Country is invalid")); + } + + [TestMethod] + public void Validate_WhenCountryIsValid_ReturnsNoValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Valid Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenStreetIsEmpty_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Street is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Street is invalid")); + } + + [TestMethod] + public void Validate_WhenStreetIsTooLong_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = new string('a', 65), + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Street is too long")); + } + + [TestMethod] + public void Validate_WhenStreetIsInvalid_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Invalid Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Street is invalid")); + } + + [TestMethod] + public void Validate_WhenStreetIsValid_ReturnsNoValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Valid Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenStateIsEmpty_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = "", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "State is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "State is invalid")); + } + + [TestMethod] + public void Validate_WhenStateIsTooLong_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = new string('a', 65), + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "State is too long")); + } + + [TestMethod] + public void Validate_WhenStateIsInvalid_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = "Invalid State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "State is invalid")); + } + + [TestMethod] + public void Validate_WhenStateIsValid_ReturnsNoValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = "Valid State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Valdate_WhenZipCodeIsTooLong_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = "State", + ZipCode = new string('0', 9) + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "ZipCode is too long")); + } + + [TestMethod] + public void Validate_WhenZipCodeIsInvalid_ReturnsValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = "State", + ZipCode = "Invalid_" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "ZipCode is invalid")); + } + + [TestMethod] + public void Validate_WhenZipCodeIsValid_ReturnsNoValidationResult() + { + var address = new AddressDto + { + City = "City", + Country = "Country", + Street = "Street", + State = "State", + ZipCode = "00-000" + }; + + var result = AddressValidator.Validate(address); + + Assert.IsFalse(result.Any()); + } + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs new file mode 100644 index 00000000..2f714be0 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs @@ -0,0 +1,65 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class CommentValidatorTests + { + [TestMethod] + public void Validate_WhenContentIsEmpty_ReturnsValidationResult() + { + var comment = new CommentDto + { + Content = "", + CreatedAt = DateTime.Now + }; + + var result = CommentValidator.Validate(comment); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Content is required")); + } + + [TestMethod] + public void Validate_WhenContentIsTooLong_ReturnsValidationResult() + { + var comment = new CommentDto + { + Content = new string('a', 1025), + CreatedAt = DateTime.Now + }; + + var result = CommentValidator.Validate(comment); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Content is too long")); + } + + [TestMethod] + public void Validate_WhenCreatedAtIsInTheFuture_ReturnsValidationResult() + { + var comment = new CommentDto + { + Content = "Content", + CreatedAt = DateTime.Now.AddMinutes(1) + }; + + var result = CommentValidator.Validate(comment); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "CreatedAt is in the future")); + } + + [TestMethod] + public void Validate_WhenCommentIsValid_ReturnsNoValidationResult() + { + var comment = new CommentDto + { + Content = "Content", + CreatedAt = DateTime.Now + }; + + var result = CommentValidator.Validate(comment); + + Assert.IsFalse(result.Any()); + } + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs new file mode 100644 index 00000000..384b52ab --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs @@ -0,0 +1,257 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class EventValidatorTests + { + [TestMethod] + public void Validate_WhenNameIsEmpty_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); + } + + [TestMethod] + public void Validate_WhenNameIsTooLong_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = new string('a', 65), + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); + } + + [TestMethod] + public void Validate_WhenNameIsValid_ReturnsNoValidationResult() + { + var event1 = new EventDto + { + Name = "ValidName", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenDescriptionIsEmpty_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Description is required")); + } + + [TestMethod] + public void Validate_WhenDescriptionIsTooLong_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = new string('a', 4049), + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Description is too long")); + } + + [TestMethod] + public void Validate_WhenDescriptionIsValid_ReturnsNoValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Valid Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenStartAtIsAfterEndAt_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now.AddMinutes(1), + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "StartTime is after EndTime")); + } + + [TestMethod] + public void Validate_WhenCreatedAtIsInTheFuture_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now.AddMinutes(1), + UpdatedAt = DateTime.Now, + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "CreatedAt is in the future")); + } + + [TestMethod] + public void Validate_WhenUpdatedAtIsInTheFuture_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now.AddMinutes(1), + Slug = "slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "UpdatedAt is in the future")); + } + + [TestMethod] + public void Validate_WhenSlugIsEmpty_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is invalid")); + } + + [TestMethod] + public void Validate_WhenSlugIsTooLong_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = new string('a', 129) + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is too long")); + } + + [TestMethod] + public void Validate_WhenSlugIsIsInvalid_ReturnsValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "invalid slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is invalid")); + } + + [TestMethod] + public void Validate_WhenSlugIsValid_ReturnsNoValidationResult() + { + var event1 = new EventDto + { + Name = "Name", + Description = "Description", + StartAt = DateTime.Now, + EndAt = DateTime.Now, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + Slug = "valid-slug" + }; + + var result = EventValidator.Validate(event1); + + Assert.IsFalse(result.Any()); + } + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs new file mode 100644 index 00000000..b1a3bd5c --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs @@ -0,0 +1,62 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class InterestValidatorTests + { + [TestMethod] + public void Validate_WhenNameIsEmpty_ReturnsValidationResult() + { + var interest = new IntrestDto + { + Name = "" + }; + + var result = InterestValidator.Validate(interest); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsTooLong_ReturnsValidationResult() + { + var interest = new IntrestDto + { + Name = new string('a', 33) + }; + + var result = InterestValidator.Validate(interest); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); + } + + [TestMethod] + public void Validate_WhenNameIsInvalid_ReturnsValidationResult() + { + var interest = new IntrestDto + { + Name = "Invalid Name" + }; + + var result = InterestValidator.Validate(interest); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsValid_ReturnsNoValidationResult() + { + var interest = new IntrestDto + { + Name = "Valid Name" + }; + + var result = InterestValidator.Validate(interest); + + Assert.IsFalse(result.Any()); + } + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs new file mode 100644 index 00000000..80fb499a --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs @@ -0,0 +1,62 @@ +using ReasnAPI.Models.Database; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class ObjectTypeValidatorTests + { + [TestMethod] + public void Validate_WhenNameIsEmpty_ReturnsValidationResult() + { + var objectType = new ObjectType + { + Name = "" + }; + + var result = ObjectTypeValidator.Validate(objectType); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsInvalid_ReturnsValidationResult() + { + var objectType = new ObjectType + { + Name = "Invalid Name" + }; + + var result = ObjectTypeValidator.Validate(objectType); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsEvent_ReturnsNoValidationResult() + { + var objectType = new ObjectType + { + Name = "Event" + }; + + var result = ObjectTypeValidator.Validate(objectType); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenNameIsUser_ReturnsNoValidationResult() + { + var objectType = new ObjectType + { + Name = "User" + }; + + var result = ObjectTypeValidator.Validate(objectType); + + Assert.IsFalse(result.Any()); + } + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs new file mode 100644 index 00000000..601f69ed --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs @@ -0,0 +1,109 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class ParameterValidatorTests + { + [TestMethod] + public void Validate_WhenKeyIsEmpty_ReturnsKeyIsRequired() + { + var parameter = new ParameterDto + { + Key = "", + Value = "value" + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is invalid")); + } + + [TestMethod] + public void Validate_WhenKeyIsTooLong_ReturnsKeyIsTooLong() + { + var parameter = new ParameterDto + { + Key = new string('a', 33), + Value = "value" + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is too long")); + } + + [TestMethod] + public void Validate_WhenKeyIsInvalid_ReturnsKeyIsInvalid() + { + var parameter = new ParameterDto + { + Key = "Invalid Key", + Value = "value" + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is invalid")); + } + + [TestMethod] + public void Validate_WhenValueIsEmpty_ReturnsValueIsRequired() + { + var parameter = new ParameterDto + { + Key = "key", + Value = "" + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is invalid")); + } + + [TestMethod] + public void Validate_WhenValueIsTooLong_ReturnsValueIsTooLong() + { + var parameter = new ParameterDto + { + Key = "key", + Value = new string('a', 65) + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is too long")); + } + + [TestMethod] + public void Validate_WhenValueIsInvalid_ReturnsValueIsInvalid() + { + var parameter = new ParameterDto + { + Key = "key", + Value = "Invalid Value" + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is invalid")); + } + + [TestMethod] + public void Validate_WhenValueAndKeyAreValid_ReturnsNoValidationResult() + { + var parameter = new ParameterDto + { + Key = "key", + Value = "value" + }; + + var result = ParameterValidator.Validate(parameter); + + Assert.IsFalse(result.Any()); + } + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs new file mode 100644 index 00000000..0509dbe1 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs @@ -0,0 +1,75 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class RoleValidatorTests + { + [TestMethod] + public void Validate_WhenRoleNameIsEmpty_ReturnsValidationResult() + { + var role = new RoleDto + { + Name = "" + }; + + var result = RoleValidator.Validate(role); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Role name is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Role name is invalid")); + } + + [TestMethod] + public void Validate_WhenRoleNameIsInvalid_ReturnsValidationResult() + { + var role = new RoleDto + { + Name = "Invalid Role" + }; + + var result = RoleValidator.Validate(role); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Role name is invalid")); + } + + [TestMethod] + public void Validate_WhenRoleNameIsOrganizer_ReturnsNoValidationResult() + { + var role = new RoleDto + { + Name = "Organizer" + }; + + var result = RoleValidator.Validate(role); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenRoleNameIsAdmin_ReturnsNoValidationResult() + { + var role = new RoleDto + { + Name = "Admin" + }; + + var result = RoleValidator.Validate(role); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenRoleNameIsUser_ReturnsNoValidationResult() + { + var role = new RoleDto + { + Name = "User" + }; + + var result = RoleValidator.Validate(role); + + Assert.IsFalse(result.Any()); + } + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs new file mode 100644 index 00000000..46a2b05b --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs @@ -0,0 +1,101 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class StatusValidatorTests + { + [TestMethod] + public void Validate_WhenNameIsEmpty_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsInvalid_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "Invalid Name" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsInterested_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "Interested" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsParticipating_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "Participating" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsCompleted_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "Completed" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsInProgress_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "In progress" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsWaitingForApproval_ReturnsValidationResult() + { + var status = new StatusDto + { + Name = "Waiting for approval" + }; + + var result = StatusValidator.Validate(status); + + Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs new file mode 100644 index 00000000..98b163b3 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs @@ -0,0 +1,62 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class TagValidatorTests + { + [TestMethod] + public void Validate_WhenNameIsEmpty_ReturnsValidationResult() + { + var tag = new TagDto + { + Name = "" + }; + + var result = TagValidator.Validate(tag); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsTooLong_ReturnsValidationResult() + { + var tag = new TagDto + { + Name = new string('a', 65) + }; + + var result = TagValidator.Validate(tag); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); + } + + [TestMethod] + public void Validate_WhenNameIsInvalid_ReturnsValidationResult() + { + var tag = new TagDto + { + Name = "Invalid Name" + }; + + var result = TagValidator.Validate(tag); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsValid_ReturnsValidationResult() + { + var tag = new TagDto + { + Name = "Valid Name" + }; + + var result = TagValidator.Validate(tag); + + Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs new file mode 100644 index 00000000..47cea2a3 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs @@ -0,0 +1,374 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.Validators +{ + [TestClass] + public class UserValidatorTests + { + [TestMethod] + public void Validate_WhenNameIsEmpty_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsTooLong_ReturnsValidationResult() + { + var user = new UserDto + { + Name = new string('a', 65), + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); + } + + [TestMethod] + public void Validate_WhenNameIsInvalid_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Invalid Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); + } + + [TestMethod] + public void Validate_WhenNameIsValid_ReturnsNoValidationResult() + { + var user = new UserDto + { + Name = "Validname", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenSurnameIsEmpty_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is invalid")); + } + + [TestMethod] + public void Validate_WhenSurnameIsTooLong_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = new string('a', 65), + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is too long")); + } + + [TestMethod] + public void Validate_WhenSurnameIsInvalid_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Invalid Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is invalid")); + } + + [TestMethod] + public void Validate_WhenSurnameIsValid_ReturnsNoValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Validsurname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenUsernameIsEmpty_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is invalid")); + } + + [TestMethod] + public void Validate_WhenUsernameIsTooLong_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = new string('a', 65), + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is too long")); + } + + [TestMethod] + public void Validate_WhenUsernameIsInvalid_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Invalid Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is invalid")); + } + + [TestMethod] + public void Validate_WhenUsernameIsValid_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "ValidUsername", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenEmailIsEmpty_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is required")); + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is invalid")); + } + + [TestMethod] + public void Validate_WhenEmailIsTooLong_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = new string('a', 256), + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is too long")); + } + + [TestMethod] + public void Validate_WhenEmailIsInvalid_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "Invalid Email", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is invalid")); + } + + [TestMethod] + public void Validate_WhenEmailIsValid_ReturnsNoValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "valid@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsFalse(result.Any()); + } + + [TestMethod] + public void Validate_WhenPhoneIsTooLong_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = new string('a', 20) + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Phone is too long")); + } + + [TestMethod] + public void Validate_WhenPhoneIsInvalid_ReturnsValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "Invalid Phone" + }; + + var result = UserValidator.Validate(user); + + Assert.IsTrue(result.Any(r => r.ErrorMessage == "Phone is invalid")); + } + + [TestMethod] + public void Validate_WhenPhoneIsValid_ReturnsNoValidationResult() + { + var user = new UserDto + { + Name = "Name", + Surname = "Surname", + Username = "Username", + RoleId = 1, + Email = "email@email.com", + AddressId = 1, + Phone = "+48 123456789" + }; + + var result = UserValidator.Validate(user); + + Assert.IsFalse(result.Any()); + } + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs index 08aa4c60..dfad3dc9 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class AddressValidator : IValidator
+ public class AddressValidator : IValidator { - public static IEnumerable Validate(Address address) + public static IEnumerable Validate(AddressDto address) { if (string.IsNullOrWhiteSpace(address.City)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("City is too long", [nameof(address.City)]); } - if (new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{Lu}\\p{Ll}+)*$").IsMatch(address.City) is false) + if (!new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{Lu}\\p{Ll}+)*$").IsMatch(address.City)) { yield return new ValidationResult("City is invalid", [nameof(address.City)]); } @@ -33,7 +33,7 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("Country is too long", [nameof(address.Country)]); } - if (new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)(\\p{Lu}\\p{Ll}+|i|of|and|the)){0,5}$").IsMatch(address.Country) is false) + if (!new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)(\\p{Lu}\\p{Ll}+|i|of|and|the)){0,5}$").IsMatch(address.Country)) { yield return new ValidationResult("Country is invalid", [nameof(address.Country)]); } @@ -48,7 +48,7 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("Street is too long", [nameof(address.Street)]); } - if (new Regex("^[\\p{L}\\d]+(?:(\\s)\\p{L}+)*(\\s(?:(\\d+\\p{L}?(/\\d*\\p{L}?)?)))?$").IsMatch(address.Street) is false) + if (!new Regex("^[\\p{L}\\d]+(?:(\\s)\\p{L}+)*(\\s(?:(\\d+\\p{L}?(/\\d*\\p{L}?)?)))?$").IsMatch(address.Street)) { yield return new ValidationResult("Street is invalid", [nameof(address.Street)]); } @@ -63,7 +63,7 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("State is too long", [nameof(address.State)]); } - if (new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{L}+)*$").IsMatch(address.State) is false) + if (!new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{L}+)*$").IsMatch(address.State)) { yield return new ValidationResult("State is invalid", [nameof(address.State)]); } @@ -75,11 +75,11 @@ public static IEnumerable Validate(Address address) yield return new ValidationResult("ZipCode is too long", [nameof(address.ZipCode)]); } - if (new Regex("^[\\p{L}\\d\\s-]{3,}$").IsMatch(address.ZipCode) is false) + if (!new Regex("^[\\p{L}\\d\\s-]{3,}$").IsMatch(address.ZipCode)) { yield return new ValidationResult("ZipCode is invalid", [nameof(address.ZipCode)]); } } } } -} +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs index e4fd2264..ea80de6c 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs @@ -1,18 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; -using System.Numerics; namespace ReasnAPI.Validators { - public class CommentValidator : IValidator + public class CommentValidator : IValidator { - public static IEnumerable Validate(Comment comment) + public static IEnumerable Validate(CommentDto comment) { - if (string.IsNullOrWhiteSpace(comment.EventId.ToString())) - { - yield return new ValidationResult("EventId is required", [nameof(comment.EventId)]); - } - if (string.IsNullOrWhiteSpace(comment.Content)) { yield return new ValidationResult("Content is required", [nameof(comment.Content)]); @@ -23,20 +17,10 @@ public static IEnumerable Validate(Comment comment) yield return new ValidationResult("Content is too long", [nameof(comment.Content)]); } - if (string.IsNullOrWhiteSpace(comment.CreatedAt.ToString())) - { - yield return new ValidationResult("CreatedAt is required", [nameof(comment.CreatedAt)]); - } - - if (comment.CreatedAt > DateTime.Now) + if (comment.CreatedAt >= DateTime.Now) { yield return new ValidationResult("CreatedAt is in the future", [nameof(comment.CreatedAt)]); } - - if (string.IsNullOrWhiteSpace(comment.UserId.ToString())) - { - yield return new ValidationResult("UserId is required", [nameof(comment.UserId)]); - } } } -} +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs index 87de07e9..cd35b64d 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class EventValidator : IValidator + public class EventValidator : IValidator { - public static IEnumerable Validate(Event eventData) + public static IEnumerable Validate(EventDto eventData) { if (string.IsNullOrWhiteSpace(eventData.Name)) { @@ -18,11 +18,6 @@ public static IEnumerable Validate(Event eventData) yield return new ValidationResult("Name is too long", [nameof(eventData.Name)]); } - if (string.IsNullOrWhiteSpace(eventData.AddressId.ToString())) - { - yield return new ValidationResult("AddressId is required", [nameof(eventData.AddressId)]); - } - if (string.IsNullOrWhiteSpace(eventData.Description)) { yield return new ValidationResult("Description is required", [nameof(eventData.Description)]); @@ -33,34 +28,19 @@ public static IEnumerable Validate(Event eventData) yield return new ValidationResult("Description is too long", [nameof(eventData.Description)]); } - if (string.IsNullOrWhiteSpace(eventData.OrganizerId.ToString())) - { - yield return new ValidationResult("OrganizerId is required", [nameof(eventData.OrganizerId)]); - } - - if (string.IsNullOrWhiteSpace(eventData.StartAt.ToString())) - { - yield return new ValidationResult("StartTime is required", [nameof(eventData.StartAt)]); - } - - if (string.IsNullOrWhiteSpace(eventData.EndAt.ToString())) - { - yield return new ValidationResult("EndTime is required", [nameof(eventData.EndAt)]); - } - if (eventData.StartAt > eventData.EndAt) { yield return new ValidationResult("StartTime is after EndTime", [nameof(eventData.StartAt)]); } - if (string.IsNullOrWhiteSpace(eventData.CreatedAt.ToString())) + if (eventData.CreatedAt >= DateTime.Now) { - yield return new ValidationResult("CreatedAt is required", [nameof(eventData.CreatedAt)]); + yield return new ValidationResult("CreatedAt is in the future", [nameof(eventData.CreatedAt)]); } - if (string.IsNullOrWhiteSpace(eventData.UpdatedAt.ToString())) + if (eventData.UpdatedAt >= DateTime.Now) { - yield return new ValidationResult("UpdatedAt is required", [nameof(eventData.UpdatedAt)]); + yield return new ValidationResult("UpdatedAt is in the future", [nameof(eventData.UpdatedAt)]); } if (string.IsNullOrWhiteSpace(eventData.Slug)) @@ -73,15 +53,10 @@ public static IEnumerable Validate(Event eventData) yield return new ValidationResult("Slug is too long", [nameof(eventData.Slug)]); } - if (new Regex("^[\\p{L}\\d]+[\\p{L}\\d-]*$").IsMatch(eventData.Slug)) + if (!new Regex("^[\\p{L}\\d]+[\\p{L}\\d-]*$").IsMatch(eventData.Slug)) { yield return new ValidationResult("Slug is invalid", [nameof(eventData.Name)]); } - - if (string.IsNullOrWhiteSpace(eventData.StatusId.ToString())) - { - yield return new ValidationResult("StatusId is required", [nameof(eventData.StatusId)]); - } } } -} +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs deleted file mode 100644 index 15de2bfc..00000000 --- a/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs +++ /dev/null @@ -1,21 +0,0 @@ -using ReasnAPI.Models.Database; -using System.ComponentModel.DataAnnotations; - -namespace ReasnAPI.Validators -{ - public class ImageValidator : IValidator - { - public static IEnumerable Validate(Image image) - { - if (string.IsNullOrWhiteSpace(image.ObjectTypeId.ToString())) - { - yield return new ValidationResult("ObjectTypeId is required", [nameof(image.ObjectTypeId)]); - } - - if (string.IsNullOrWhiteSpace(image.ObjectId.ToString())) - { - yield return new ValidationResult("ObjectId is required", [nameof(image.ObjectId)]); - } - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs index ce4704ed..d65fc8fb 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class InterestValidator : IValidator + public class InterestValidator : IValidator { - public static IEnumerable Validate(Interest interest) + public static IEnumerable Validate(IntrestDto interest) { if (string.IsNullOrWhiteSpace(interest.Name)) { @@ -18,10 +18,10 @@ public static IEnumerable Validate(Interest interest) yield return new ValidationResult("Name is too long", [nameof(interest.Name)]); } - if (new Regex("^\\p{Lu}\\p{Ll}+(?:\\s\\p{L}+)*$").IsMatch(interest.Name)) + if (!new Regex("^\\p{Lu}\\p{Ll}+(?:\\s\\p{L}+)*$").IsMatch(interest.Name)) { yield return new ValidationResult("Name is invalid", [nameof(interest.Name)]); } } } -} +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs index c26bddaf..af303d50 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs @@ -13,15 +13,10 @@ public static IEnumerable Validate(ObjectType objectType) yield return new ValidationResult("Name is required", [nameof(objectType.Name)]); } - if (objectType.Name.Length > 32) - { - yield return new ValidationResult("Name is too long", [nameof(objectType.Name)]); - } - - if (new Regex("^(Event|User)$").IsMatch(objectType.Name) is false) + if (!new Regex("^(Event|User)$").IsMatch(objectType.Name)) { yield return new ValidationResult("Name is invalid", [nameof(objectType.Name)]); } } } -} +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs index 8a06fe21..c4e64206 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class ParameterValidator : IValidator + public class ParameterValidator : IValidator { - public static IEnumerable Validate(Parameter parameter) + public static IEnumerable Validate(ParameterDto parameter) { if (string.IsNullOrWhiteSpace(parameter.Key)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(Parameter parameter) yield return new ValidationResult("Key is too long", [nameof(parameter.Key)]); } - if (new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(parameter.Key)) + if (!new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(parameter.Key)) { yield return new ValidationResult("Key is invalid", [nameof(parameter.Key)]); } @@ -33,10 +33,10 @@ public static IEnumerable Validate(Parameter parameter) yield return new ValidationResult("Value is too long", [nameof(parameter.Value)]); } - if (new Regex("^[\\p{L}\\d]+(?:\\s[\\p{L}\\d]+)*$").IsMatch(parameter.Value)) + if (!new Regex("^[\\p{L}\\d]+(?:\\s[\\p{L}\\d]+)*$").IsMatch(parameter.Value)) { yield return new ValidationResult("Value is invalid", [nameof(parameter.Value)]); } } } -} +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs index 362a9fc9..90598e29 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs @@ -1,27 +1,22 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class RoleValidator : IValidator + public class RoleValidator : IValidator { - public static IEnumerable Validate(Role role) + public static IEnumerable Validate(RoleDto role) { if (string.IsNullOrWhiteSpace(role.Name)) { yield return new ValidationResult("Role name is required", [nameof(role.Name)]); } - if (role.Name.Length > 32) - { - yield return new ValidationResult("Role name is too long", [nameof(role.Name)]); - } - - if (new Regex("^(Organizer|Admin|User)$").IsMatch(role.Name) is false) + if (!new Regex("^(Organizer|Admin|User)$").IsMatch(role.Name)) { yield return new ValidationResult("Role name is invalid", [nameof(role.Name)]); } } } -} +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs index a28e7bb1..4ec34e93 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs @@ -1,32 +1,22 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class StatusValidator : IValidator + public class StatusValidator : IValidator { - public static IEnumerable Validate(Status status) + public static IEnumerable Validate(StatusDto status) { if (string.IsNullOrWhiteSpace(status.Name)) { yield return new ValidationResult("Name is required", [nameof(status.Name)]); } - if (status.Name.Length > 32) - { - yield return new ValidationResult("Name is too long", [nameof(status.Name)]); - } - - if (string.IsNullOrWhiteSpace(status.ObjectTypeId.ToString())) - { - yield return new ValidationResult("ObjectTypeId is required", [nameof(status.ObjectTypeId)]); - } - - if (new Regex("^(Interested|Participating|Completed|In progress|Waiting for approval)$").IsMatch(status.Name) is false) + if (!new Regex("^(Interested|Participating|Completed|In progress|Waiting for approval)$").IsMatch(status.Name)) { yield return new ValidationResult("Name is invalid", [nameof(status.Name)]); } } } -} +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs index ff7ee67c..f871c817 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class TagValidator : IValidator + public class TagValidator : IValidator { - public static IEnumerable Validate(Tag tag) + public static IEnumerable Validate(TagDto tag) { if (string.IsNullOrWhiteSpace(tag.Name)) { @@ -18,10 +18,10 @@ public static IEnumerable Validate(Tag tag) yield return new ValidationResult("Name is too long", [nameof(tag.Name)]); } - if (new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(tag.Name)) + if (!new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(tag.Name)) { yield return new ValidationResult("Name is invalid", [nameof(tag.Name)]); } } } -} +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs index b6dfb0d0..77602102 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs @@ -1,12 +1,12 @@ -using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; namespace ReasnAPI.Validators { - public class UserValidator : IValidator + public class UserValidator : IValidator { - public static IEnumerable Validate(User user) + public static IEnumerable Validate(UserDto user) { if (string.IsNullOrWhiteSpace(user.Name)) { @@ -18,7 +18,7 @@ public static IEnumerable Validate(User user) yield return new ValidationResult("Name is too long", [nameof(user.Name)]); } - if (new Regex("^\\p{Lu}\\p{Ll}+$").IsMatch(user.Name) is false) + if (!new Regex("^\\p{Lu}\\p{Ll}+$").IsMatch(user.Name)) { yield return new ValidationResult("Name is invalid", [nameof(user.Name)]); } @@ -33,7 +33,7 @@ public static IEnumerable Validate(User user) yield return new ValidationResult("Surname is too long", [nameof(user.Surname)]); } - if (new Regex("^\\p{L}+(?:[\\s'-]?\\p{L}+)*$").IsMatch(user.Surname) is false) + if (!new Regex("^\\p{L}+(?:[\\s'-]?\\p{L}+)*$").IsMatch(user.Surname)) { yield return new ValidationResult("Surname is invalid", [nameof(user.Surname)]); } @@ -48,31 +48,11 @@ public static IEnumerable Validate(User user) yield return new ValidationResult("Username is too long", [nameof(user.Username)]); } - if (new Regex("^[\\p{L}\\d._%+-]+$").IsMatch(user.Username) is false) + if (!new Regex("^[\\p{L}\\d._%+-]+$").IsMatch(user.Username)) { yield return new ValidationResult("Username is invalid", [nameof(user.Username)]); } - if (string.IsNullOrWhiteSpace(user.Password)) - { - yield return new ValidationResult("Password is required", [nameof(user.Password)]); - } - - if (string.IsNullOrWhiteSpace(user.CreatedAt.ToString())) - { - yield return new ValidationResult("CreatedAt is required", [nameof(user.CreatedAt)]); - } - - if (string.IsNullOrWhiteSpace(user.UpdatedAt.ToString())) - { - yield return new ValidationResult("UpdatedAt is required", [nameof(user.UpdatedAt)]); - } - - if (string.IsNullOrWhiteSpace(user.RoleId.ToString())) - { - yield return new ValidationResult("RoleId is required", [nameof(user.RoleId)]); - } - if (string.IsNullOrWhiteSpace(user.Email)) { yield return new ValidationResult("Email is required", [nameof(user.Email)]); @@ -83,24 +63,19 @@ public static IEnumerable Validate(User user) yield return new ValidationResult("Email is too long", [nameof(user.Email)]); } - if (new Regex("^[a-zA-Z\\d._%+-]+@[a-zA-Z\\d.-]+\\.[a-zA-Z]{2,6}$").IsMatch(user.Email) is false) + if (!new Regex("^[a-zA-Z\\d._%+-]+@[a-zA-Z\\d.-]+\\.[a-zA-Z]{2,6}$").IsMatch(user.Email)) { yield return new ValidationResult("Email is invalid", [nameof(user.Email)]); } - if (string.IsNullOrWhiteSpace(user.AddressId.ToString())) - { - yield return new ValidationResult("AddressId is required", [nameof(user.AddressId)]); - } - if (!string.IsNullOrWhiteSpace(user.Phone)) { - if (!string.IsNullOrWhiteSpace(user.Phone) && user.Phone.Length > 16) + if (user.Phone.Length > 16) { yield return new ValidationResult("Phone is too long", [nameof(user.Phone)]); } - if (new Regex("^\\+\\d{1,3}\\s\\d{1,15}$").IsMatch(user.Phone) is false) + if (!new Regex("^\\+\\d{1,3}\\s\\d{1,15}$").IsMatch(user.Phone)) { yield return new ValidationResult("Phone is invalid", [nameof(user.Phone)]); } @@ -108,4 +83,4 @@ public static IEnumerable Validate(User user) } } -} +} \ No newline at end of file From 4ace7799d93790689dce077c23c6e22fb5e2f99f Mon Sep 17 00:00:00 2001 From: Maciej Koperdowski Date: Mon, 13 May 2024 21:16:38 +0200 Subject: [PATCH 15/24] Unit test fix --- .../Validators/EventValidatorTests.cs | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs index 384b52ab..aa4839c9 100644 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs @@ -1,5 +1,6 @@ using ReasnAPI.Models.DTOs; using ReasnAPI.Validators; +using System; namespace ReasnAPI.Tests.Validators { @@ -14,7 +15,7 @@ public void Validate_WhenNameIsEmpty_ReturnsValidationResult() Name = "", Description = "Description", StartAt = DateTime.Now, - EndAt = DateTime.Now, + EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, Slug = "slug" @@ -33,7 +34,7 @@ public void Validate_WhenNameIsTooLong_ReturnsValidationResult() Name = new string('a', 65), Description = "Description", StartAt = DateTime.Now, - EndAt = DateTime.Now, + EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, Slug = "slug" @@ -52,7 +53,7 @@ public void Validate_WhenNameIsValid_ReturnsNoValidationResult() Name = "ValidName", Description = "Description", StartAt = DateTime.Now, - EndAt = DateTime.Now, + EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, Slug = "slug" @@ -71,7 +72,7 @@ public void Validate_WhenDescriptionIsEmpty_ReturnsValidationResult() Name = "Name", Description = "", StartAt = DateTime.Now, - EndAt = DateTime.Now, + EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, Slug = "slug" @@ -90,7 +91,7 @@ public void Validate_WhenDescriptionIsTooLong_ReturnsValidationResult() Name = "Name", Description = new string('a', 4049), StartAt = DateTime.Now, - EndAt = DateTime.Now, + EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, Slug = "slug" @@ -109,7 +110,7 @@ public void Validate_WhenDescriptionIsValid_ReturnsNoValidationResult() Name = "Name", Description = "Valid Description", StartAt = DateTime.Now, - EndAt = DateTime.Now, + EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, Slug = "slug" @@ -147,7 +148,7 @@ public void Validate_WhenCreatedAtIsInTheFuture_ReturnsValidationResult() Name = "Name", Description = "Description", StartAt = DateTime.Now, - EndAt = DateTime.Now, + EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now.AddMinutes(1), UpdatedAt = DateTime.Now, Slug = "slug" @@ -166,7 +167,7 @@ public void Validate_WhenUpdatedAtIsInTheFuture_ReturnsValidationResult() Name = "Name", Description = "Description", StartAt = DateTime.Now, - EndAt = DateTime.Now, + EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now.AddMinutes(1), Slug = "slug" @@ -185,7 +186,7 @@ public void Validate_WhenSlugIsEmpty_ReturnsValidationResult() Name = "Name", Description = "Description", StartAt = DateTime.Now, - EndAt = DateTime.Now, + EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, Slug = "" @@ -205,7 +206,7 @@ public void Validate_WhenSlugIsTooLong_ReturnsValidationResult() Name = "Name", Description = "Description", StartAt = DateTime.Now, - EndAt = DateTime.Now, + EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, Slug = new string('a', 129) @@ -224,7 +225,7 @@ public void Validate_WhenSlugIsIsInvalid_ReturnsValidationResult() Name = "Name", Description = "Description", StartAt = DateTime.Now, - EndAt = DateTime.Now, + EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, Slug = "invalid slug" @@ -243,7 +244,7 @@ public void Validate_WhenSlugIsValid_ReturnsNoValidationResult() Name = "Name", Description = "Description", StartAt = DateTime.Now, - EndAt = DateTime.Now, + EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, Slug = "valid-slug" From 934e4451c2ba30538a2ee881c8fc7ec74ec7f6ee Mon Sep 17 00:00:00 2001 From: Maciej Koperdowski Date: Tue, 14 May 2024 10:39:26 +0200 Subject: [PATCH 16/24] Restore ReasnAPI.csproj --- Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj b/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj index 02ce3550..23499ae8 100644 --- a/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj +++ b/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj @@ -25,6 +25,7 @@ + From dee72d62617a01ccb1f6e44bf61fe20704463ef5 Mon Sep 17 00:00:00 2001 From: Maciej Koperdowski Date: Wed, 15 May 2024 18:20:23 +0200 Subject: [PATCH 17/24] Created const variables for regex strings and hardcoded numbers --- .../ReasnAPI/Validators/AddressValidator.cs | 31 +++++++++++++------ .../ReasnAPI/Validators/CommentValidator.cs | 4 ++- .../ReasnAPI/Validators/EventValidator.cs | 13 +++++--- .../ReasnAPI/Validators/InterestValidator.cs | 7 +++-- .../ReasnAPI/Validators/ParameterValidator.cs | 13 +++++--- .../ReasnAPI/Validators/TagValidator.cs | 7 +++-- 6 files changed, 52 insertions(+), 23 deletions(-) diff --git a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs index dfad3dc9..6a7b5214 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs @@ -6,6 +6,17 @@ namespace ReasnAPI.Validators { public class AddressValidator : IValidator { + private const int CityMaxLength = 64; + private const string CityRegexPattern = "^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{Lu}\\p{Ll}+)*$"; + private const int CountryMaxLength = 64; + private const string CountryRegexPattern = "^\\p{Lu}\\p{Ll}+(?:(\\s|-)(\\p{Lu}\\p{Ll}+|i|of|and|the)){0,5}$"; + private const int StreetMaxLength = 64; + private const string StreetRegexPattern = "^[\\p{L}\\d]+(?:(\\s)\\p{L}+)*(\\s(?:(\\d+\\p{L}?(/\\d*\\p{L}?)?)))?$"; + private const int StateMaxLength = 64; + private const string StateRegexPattern = "^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{L}+)*$"; + private const int ZipCodeMaxLength = 8; + private const string ZipCodeRegexPattern = "^[\\p{L}\\d\\s-]{3,}$"; + public static IEnumerable Validate(AddressDto address) { if (string.IsNullOrWhiteSpace(address.City)) @@ -13,12 +24,12 @@ public static IEnumerable Validate(AddressDto address) yield return new ValidationResult("City is required", [nameof(address.City)]); } - if (address.City.Length > 64) + if (address.City.Length > CityMaxLength) { yield return new ValidationResult("City is too long", [nameof(address.City)]); } - if (!new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{Lu}\\p{Ll}+)*$").IsMatch(address.City)) + if (!new Regex(CityRegexPattern).IsMatch(address.City)) { yield return new ValidationResult("City is invalid", [nameof(address.City)]); } @@ -28,12 +39,12 @@ public static IEnumerable Validate(AddressDto address) yield return new ValidationResult("Country is required", [nameof(address.Country)]); } - if (address.Country.Length > 64) + if (address.Country.Length > CountryMaxLength) { yield return new ValidationResult("Country is too long", [nameof(address.Country)]); } - if (!new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)(\\p{Lu}\\p{Ll}+|i|of|and|the)){0,5}$").IsMatch(address.Country)) + if (!new Regex(CountryRegexPattern).IsMatch(address.Country)) { yield return new ValidationResult("Country is invalid", [nameof(address.Country)]); } @@ -43,12 +54,12 @@ public static IEnumerable Validate(AddressDto address) yield return new ValidationResult("Street is required", [nameof(address.Street)]); } - if (address.Street.Length > 64) + if (address.Street.Length > StreetMaxLength) { yield return new ValidationResult("Street is too long", [nameof(address.Street)]); } - if (!new Regex("^[\\p{L}\\d]+(?:(\\s)\\p{L}+)*(\\s(?:(\\d+\\p{L}?(/\\d*\\p{L}?)?)))?$").IsMatch(address.Street)) + if (!new Regex(StreetRegexPattern).IsMatch(address.Street)) { yield return new ValidationResult("Street is invalid", [nameof(address.Street)]); } @@ -58,24 +69,24 @@ public static IEnumerable Validate(AddressDto address) yield return new ValidationResult("State is required", [nameof(address.State)]); } - if (address.State.Length > 64) + if (address.State.Length > StateMaxLength) { yield return new ValidationResult("State is too long", [nameof(address.State)]); } - if (!new Regex("^\\p{Lu}\\p{Ll}+(?:(\\s|-)\\p{L}+)*$").IsMatch(address.State)) + if (!new Regex(StateRegexPattern).IsMatch(address.State)) { yield return new ValidationResult("State is invalid", [nameof(address.State)]); } if (!string.IsNullOrWhiteSpace(address.ZipCode)) { - if (address.ZipCode.Length > 8) + if (address.ZipCode.Length > ZipCodeMaxLength) { yield return new ValidationResult("ZipCode is too long", [nameof(address.ZipCode)]); } - if (!new Regex("^[\\p{L}\\d\\s-]{3,}$").IsMatch(address.ZipCode)) + if (!new Regex(ZipCodeRegexPattern).IsMatch(address.ZipCode)) { yield return new ValidationResult("ZipCode is invalid", [nameof(address.ZipCode)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs index ea80de6c..f0d7efe8 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs @@ -5,6 +5,8 @@ namespace ReasnAPI.Validators { public class CommentValidator : IValidator { + private const int ContentMaxLength = 1024; + public static IEnumerable Validate(CommentDto comment) { if (string.IsNullOrWhiteSpace(comment.Content)) @@ -12,7 +14,7 @@ public static IEnumerable Validate(CommentDto comment) yield return new ValidationResult("Content is required", [nameof(comment.Content)]); } - if (comment.Content.Length > 1024) + if (comment.Content.Length > ContentMaxLength) { yield return new ValidationResult("Content is too long", [nameof(comment.Content)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs index cd35b64d..d313de3f 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs @@ -6,6 +6,11 @@ namespace ReasnAPI.Validators { public class EventValidator : IValidator { + private const int NameMaxLength = 64; + private const int DescriptionMaxLength = 4048; + private const int SlugMaxLength = 128; + private const string SlugRegexPattern = "^[\\p{L}\\d]+[\\p{L}\\d-]*$"; + public static IEnumerable Validate(EventDto eventData) { if (string.IsNullOrWhiteSpace(eventData.Name)) @@ -13,7 +18,7 @@ public static IEnumerable Validate(EventDto eventData) yield return new ValidationResult("Name is required", [nameof(eventData.Name)]); } - if (eventData.Name.Length > 64) + if (eventData.Name.Length > NameMaxLength) { yield return new ValidationResult("Name is too long", [nameof(eventData.Name)]); } @@ -23,7 +28,7 @@ public static IEnumerable Validate(EventDto eventData) yield return new ValidationResult("Description is required", [nameof(eventData.Description)]); } - if (eventData.Description.Length > 4048) + if (eventData.Description.Length > DescriptionMaxLength) { yield return new ValidationResult("Description is too long", [nameof(eventData.Description)]); } @@ -48,12 +53,12 @@ public static IEnumerable Validate(EventDto eventData) yield return new ValidationResult("Slug is required", [nameof(eventData.Slug)]); } - if (eventData.Slug.Length > 128) + if (eventData.Slug.Length > SlugMaxLength) { yield return new ValidationResult("Slug is too long", [nameof(eventData.Slug)]); } - if (!new Regex("^[\\p{L}\\d]+[\\p{L}\\d-]*$").IsMatch(eventData.Slug)) + if (!new Regex(SlugRegexPattern).IsMatch(eventData.Slug)) { yield return new ValidationResult("Slug is invalid", [nameof(eventData.Name)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs index d65fc8fb..6c93ada2 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs @@ -6,6 +6,9 @@ namespace ReasnAPI.Validators { public class InterestValidator : IValidator { + private const int NameMaxLength = 32; + private const string NameRegexPattern = "^\\p{Lu}\\p{Ll}+(?:\\s\\p{L}+)*$"; + public static IEnumerable Validate(IntrestDto interest) { if (string.IsNullOrWhiteSpace(interest.Name)) @@ -13,12 +16,12 @@ public static IEnumerable Validate(IntrestDto interest) yield return new ValidationResult("Name is required", [nameof(interest.Name)]); } - if (interest.Name.Length > 32) + if (interest.Name.Length > NameMaxLength) { yield return new ValidationResult("Name is too long", [nameof(interest.Name)]); } - if (!new Regex("^\\p{Lu}\\p{Ll}+(?:\\s\\p{L}+)*$").IsMatch(interest.Name)) + if (!new Regex(NameRegexPattern).IsMatch(interest.Name)) { yield return new ValidationResult("Name is invalid", [nameof(interest.Name)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs index c4e64206..4dca0be0 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs @@ -6,6 +6,11 @@ namespace ReasnAPI.Validators { public class ParameterValidator : IValidator { + private const int KeyMaxLength = 32; + private const string KeyRegexPattern = "^\\p{L}+(?:\\s\\p{L}+)*$"; + private const int ValueMaxLength = 64; + private const string ValueRegexPattern = "^[\\p{L}\\d]+(?:\\s[\\p{L}\\d]+)*$"; + public static IEnumerable Validate(ParameterDto parameter) { if (string.IsNullOrWhiteSpace(parameter.Key)) @@ -13,12 +18,12 @@ public static IEnumerable Validate(ParameterDto parameter) yield return new ValidationResult("Key is required", [nameof(parameter.Key)]); } - if (parameter.Key.Length > 32) + if (parameter.Key.Length > KeyMaxLength) { yield return new ValidationResult("Key is too long", [nameof(parameter.Key)]); } - if (!new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(parameter.Key)) + if (!new Regex(KeyRegexPattern).IsMatch(parameter.Key)) { yield return new ValidationResult("Key is invalid", [nameof(parameter.Key)]); } @@ -28,12 +33,12 @@ public static IEnumerable Validate(ParameterDto parameter) yield return new ValidationResult("Value is required", [nameof(parameter.Value)]); } - if (parameter.Value.Length > 64) + if (parameter.Value.Length > ValueMaxLength) { yield return new ValidationResult("Value is too long", [nameof(parameter.Value)]); } - if (!new Regex("^[\\p{L}\\d]+(?:\\s[\\p{L}\\d]+)*$").IsMatch(parameter.Value)) + if (!new Regex(ValueRegexPattern).IsMatch(parameter.Value)) { yield return new ValidationResult("Value is invalid", [nameof(parameter.Value)]); } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs index f871c817..1691512d 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs @@ -6,6 +6,9 @@ namespace ReasnAPI.Validators { public class TagValidator : IValidator { + private const int NameMaxLength = 64; + private const string NameRegexPattern = "^\\p{L}+(?:\\s\\p{L}+)*$"; + public static IEnumerable Validate(TagDto tag) { if (string.IsNullOrWhiteSpace(tag.Name)) @@ -13,12 +16,12 @@ public static IEnumerable Validate(TagDto tag) yield return new ValidationResult("Name is required", [nameof(tag.Name)]); } - if (tag.Name.Length > 64) + if (tag.Name.Length > NameMaxLength) { yield return new ValidationResult("Name is too long", [nameof(tag.Name)]); } - if (!new Regex("^\\p{L}+(?:\\s\\p{L}+)*$").IsMatch(tag.Name)) + if (!new Regex(NameRegexPattern).IsMatch(tag.Name)) { yield return new ValidationResult("Name is invalid", [nameof(tag.Name)]); } From 208050ca167853d7a04651867ca5030d6594f4bc Mon Sep 17 00:00:00 2001 From: Maciej Koperdowski Date: Tue, 21 May 2024 01:09:35 +0200 Subject: [PATCH 18/24] Updated validator after scaffold --- .../ReasnAPI/Validators/EventValidator.cs | 6 ++++ .../ReasnAPI/Validators/ImageValidator.cs | 19 ++++++++++ .../ReasnAPI/Validators/InterestValidator.cs | 4 +-- .../Validators/ObjectTypeValidator.cs | 22 ------------ .../Validators/ParticipantValidator.cs | 19 ++++++++++ .../ReasnAPI/Validators/RoleValidator.cs | 22 ------------ .../ReasnAPI/Validators/StatusValidator.cs | 22 ------------ .../ReasnAPI/Validators/UserValidator.cs | 36 +++++++++++++------ 8 files changed, 72 insertions(+), 78 deletions(-) create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs delete mode 100644 Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/ParticipantValidator.cs delete mode 100644 Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs delete mode 100644 Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs diff --git a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs index d313de3f..85e31be5 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs @@ -10,6 +10,7 @@ public class EventValidator : IValidator private const int DescriptionMaxLength = 4048; private const int SlugMaxLength = 128; private const string SlugRegexPattern = "^[\\p{L}\\d]+[\\p{L}\\d-]*$"; + private const string StatusRegexPattern = "^(Completed|In progress|Approved|Waiting for aproval)$"; public static IEnumerable Validate(EventDto eventData) { @@ -62,6 +63,11 @@ public static IEnumerable Validate(EventDto eventData) { yield return new ValidationResult("Slug is invalid", [nameof(eventData.Name)]); } + + if (!new Regex(StatusRegexPattern).IsMatch(eventData.Status.ToString())) + { + yield return new ValidationResult("Status is invalid", [nameof(eventData.Status)]); + } } } } \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs new file mode 100644 index 00000000..5b3cda6f --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs @@ -0,0 +1,19 @@ +using ReasnAPI.Models.DTOs; +using System.ComponentModel.DataAnnotations; +using System.Text.RegularExpressions; + +namespace ReasnAPI.Validators +{ + public class ImageValidator : IValidator + { + private const string ObjectTypeRegexPattern = "^(Event|User)$"; + + public static IEnumerable Validate(ImageDto image) + { + if (!new Regex(ObjectTypeRegexPattern).IsMatch(image.ObjectType.ToString())) + { + yield return new ValidationResult("Object type is invalid", [nameof(image.ObjectType)]); + } + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs index 6c93ada2..cfcb76f5 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs @@ -4,12 +4,12 @@ namespace ReasnAPI.Validators { - public class InterestValidator : IValidator + public class InterestValidator : IValidator { private const int NameMaxLength = 32; private const string NameRegexPattern = "^\\p{Lu}\\p{Ll}+(?:\\s\\p{L}+)*$"; - public static IEnumerable Validate(IntrestDto interest) + public static IEnumerable Validate(InterestDto interest) { if (string.IsNullOrWhiteSpace(interest.Name)) { diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs deleted file mode 100644 index af303d50..00000000 --- a/Server/ReasnAPI/ReasnAPI/Validators/ObjectTypeValidator.cs +++ /dev/null @@ -1,22 +0,0 @@ -using ReasnAPI.Models.Database; -using System.ComponentModel.DataAnnotations; -using System.Text.RegularExpressions; - -namespace ReasnAPI.Validators -{ - public class ObjectTypeValidator : IValidator - { - public static IEnumerable Validate(ObjectType objectType) - { - if (string.IsNullOrWhiteSpace(objectType.Name)) - { - yield return new ValidationResult("Name is required", [nameof(objectType.Name)]); - } - - if (!new Regex("^(Event|User)$").IsMatch(objectType.Name)) - { - yield return new ValidationResult("Name is invalid", [nameof(objectType.Name)]); - } - } - } -} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ParticipantValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ParticipantValidator.cs new file mode 100644 index 00000000..6da0b100 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/ParticipantValidator.cs @@ -0,0 +1,19 @@ +using ReasnAPI.Models.DTOs; +using System.ComponentModel.DataAnnotations; +using System.Text.RegularExpressions; + +namespace ReasnAPI.Validators +{ + public class ParticipantValidator : IValidator + { + private const string StatusRegexPattern = "^(Interested|Participating)$"; + + public static IEnumerable Validate(ParticipantDto participant) + { + if (!new Regex(StatusRegexPattern).IsMatch(participant.Status.ToString())) + { + yield return new ValidationResult("Status is invalid", [nameof(participant.Status)]); + } + } + } +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs deleted file mode 100644 index 90598e29..00000000 --- a/Server/ReasnAPI/ReasnAPI/Validators/RoleValidator.cs +++ /dev/null @@ -1,22 +0,0 @@ -using ReasnAPI.Models.DTOs; -using System.ComponentModel.DataAnnotations; -using System.Text.RegularExpressions; - -namespace ReasnAPI.Validators -{ - public class RoleValidator : IValidator - { - public static IEnumerable Validate(RoleDto role) - { - if (string.IsNullOrWhiteSpace(role.Name)) - { - yield return new ValidationResult("Role name is required", [nameof(role.Name)]); - } - - if (!new Regex("^(Organizer|Admin|User)$").IsMatch(role.Name)) - { - yield return new ValidationResult("Role name is invalid", [nameof(role.Name)]); - } - } - } -} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs deleted file mode 100644 index 4ec34e93..00000000 --- a/Server/ReasnAPI/ReasnAPI/Validators/StatusValidator.cs +++ /dev/null @@ -1,22 +0,0 @@ -using ReasnAPI.Models.DTOs; -using System.ComponentModel.DataAnnotations; -using System.Text.RegularExpressions; - -namespace ReasnAPI.Validators -{ - public class StatusValidator : IValidator - { - public static IEnumerable Validate(StatusDto status) - { - if (string.IsNullOrWhiteSpace(status.Name)) - { - yield return new ValidationResult("Name is required", [nameof(status.Name)]); - } - - if (!new Regex("^(Interested|Participating|Completed|In progress|Waiting for approval)$").IsMatch(status.Name)) - { - yield return new ValidationResult("Name is invalid", [nameof(status.Name)]); - } - } - } -} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs index 77602102..2c830160 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs @@ -6,6 +6,18 @@ namespace ReasnAPI.Validators { public class UserValidator : IValidator { + private const int NameMaxLength = 64; + private const string NameRegexPattern = "^\\p{Lu}\\p{Ll}+$"; + private const int SurnameMaxLength = 64; + private const string SurnameRegexPattern = "^\\p{L}+(?:[\\s'-]?\\p{L}+)*$"; + private const int UsernameMaxLength = 64; + private const string UsernameRegexPattern = "^[\\p{L}\\d._%+-]+$"; + private const int EmailMaxLength = 255; + private const string EmailRegexPattern = "^[a-zA-Z\\d._%+-]+@[a-zA-Z\\d.-]+\\.[a-zA-Z]{2,6}$"; + private const int PhoneMaxLength = 16; + private const string PhoneRegexPattern = "^\\+\\d{1,3}\\s\\d{1,15}$"; + private const string RoleRegexPattern = "^(Admin|User|Organizer)$"; + public static IEnumerable Validate(UserDto user) { if (string.IsNullOrWhiteSpace(user.Name)) @@ -13,12 +25,12 @@ public static IEnumerable Validate(UserDto user) yield return new ValidationResult("Name is required", [nameof(user.Name)]); } - if (user.Name.Length > 64) + if (user.Name.Length > NameMaxLength) { yield return new ValidationResult("Name is too long", [nameof(user.Name)]); } - if (!new Regex("^\\p{Lu}\\p{Ll}+$").IsMatch(user.Name)) + if (!new Regex(NameRegexPattern).IsMatch(user.Name)) { yield return new ValidationResult("Name is invalid", [nameof(user.Name)]); } @@ -28,12 +40,12 @@ public static IEnumerable Validate(UserDto user) yield return new ValidationResult("Surname is required", [nameof(user.Surname)]); } - if (user.Surname.Length > 64) + if (user.Surname.Length > SurnameMaxLength) { yield return new ValidationResult("Surname is too long", [nameof(user.Surname)]); } - if (!new Regex("^\\p{L}+(?:[\\s'-]?\\p{L}+)*$").IsMatch(user.Surname)) + if (!new Regex(SurnameRegexPattern).IsMatch(user.Surname)) { yield return new ValidationResult("Surname is invalid", [nameof(user.Surname)]); } @@ -43,12 +55,12 @@ public static IEnumerable Validate(UserDto user) yield return new ValidationResult("Username is required", [nameof(user.Username)]); } - if (user.Username.Length > 64) + if (user.Username.Length > UsernameMaxLength) { yield return new ValidationResult("Username is too long", [nameof(user.Username)]); } - if (!new Regex("^[\\p{L}\\d._%+-]+$").IsMatch(user.Username)) + if (!new Regex(UsernameRegexPattern).IsMatch(user.Username)) { yield return new ValidationResult("Username is invalid", [nameof(user.Username)]); } @@ -58,29 +70,33 @@ public static IEnumerable Validate(UserDto user) yield return new ValidationResult("Email is required", [nameof(user.Email)]); } - if (user.Email.Length > 255) + if (user.Email.Length > EmailMaxLength) { yield return new ValidationResult("Email is too long", [nameof(user.Email)]); } - if (!new Regex("^[a-zA-Z\\d._%+-]+@[a-zA-Z\\d.-]+\\.[a-zA-Z]{2,6}$").IsMatch(user.Email)) + if (!new Regex(EmailRegexPattern).IsMatch(user.Email)) { yield return new ValidationResult("Email is invalid", [nameof(user.Email)]); } if (!string.IsNullOrWhiteSpace(user.Phone)) { - if (user.Phone.Length > 16) + if (user.Phone.Length > PhoneMaxLength) { yield return new ValidationResult("Phone is too long", [nameof(user.Phone)]); } - if (!new Regex("^\\+\\d{1,3}\\s\\d{1,15}$").IsMatch(user.Phone)) + if (!new Regex(PhoneRegexPattern).IsMatch(user.Phone)) { yield return new ValidationResult("Phone is invalid", [nameof(user.Phone)]); } } + if (!new Regex(RoleRegexPattern).IsMatch(user.Role.ToString())) + { + yield return new ValidationResult("Role is invalid", [nameof(user.Role)]); + } } } } \ No newline at end of file From 9a151d0b0b330850676a52031a156f7d97b5f329 Mon Sep 17 00:00:00 2001 From: Maciej Koperdowski Date: Tue, 21 May 2024 01:33:52 +0200 Subject: [PATCH 19/24] Updated unit tests after scaffold --- .../Validators/EventValidatorTests.cs | 41 ++++--- .../Validators/InterestValidatorTests.cs | 8 +- .../Validators/ObjectTypeValidatorTests.cs | 62 ----------- .../Validators/RoleValidatorTests.cs | 75 ------------- .../Validators/StatusValidatorTests.cs | 101 ------------------ .../Validators/UserValidatorTests.cs | 39 +++---- .../ReasnAPI/Validators/EventValidator.cs | 6 -- .../ReasnAPI/Validators/ImageValidator.cs | 19 ---- .../Validators/ParticipantValidator.cs | 19 ---- .../ReasnAPI/Validators/UserValidator.cs | 6 -- 10 files changed, 51 insertions(+), 325 deletions(-) delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs delete mode 100644 Server/ReasnAPI/ReasnAPI/Validators/ParticipantValidator.cs diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs index aa4839c9..06da3702 100644 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs @@ -1,6 +1,6 @@ using ReasnAPI.Models.DTOs; +using ReasnAPI.Models.Enums; using ReasnAPI.Validators; -using System; namespace ReasnAPI.Tests.Validators { @@ -18,7 +18,8 @@ public void Validate_WhenNameIsEmpty_ReturnsValidationResult() EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, - Slug = "slug" + Slug = "slug", + Status = EventStatus.Completed }; var result = EventValidator.Validate(event1); @@ -37,7 +38,8 @@ public void Validate_WhenNameIsTooLong_ReturnsValidationResult() EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, - Slug = "slug" + Slug = "slug", + Status = EventStatus.WaitingForApproval }; var result = EventValidator.Validate(event1); @@ -56,7 +58,8 @@ public void Validate_WhenNameIsValid_ReturnsNoValidationResult() EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, - Slug = "slug" + Slug = "slug", + Status = EventStatus.Inprogress }; var result = EventValidator.Validate(event1); @@ -75,7 +78,8 @@ public void Validate_WhenDescriptionIsEmpty_ReturnsValidationResult() EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, - Slug = "slug" + Slug = "slug", + Status = EventStatus.Inprogress }; var result = EventValidator.Validate(event1); @@ -94,7 +98,8 @@ public void Validate_WhenDescriptionIsTooLong_ReturnsValidationResult() EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, - Slug = "slug" + Slug = "slug", + Status = EventStatus.Approved }; var result = EventValidator.Validate(event1); @@ -113,7 +118,8 @@ public void Validate_WhenDescriptionIsValid_ReturnsNoValidationResult() EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, - Slug = "slug" + Slug = "slug", + Status = EventStatus.WaitingForApproval }; var result = EventValidator.Validate(event1); @@ -132,7 +138,8 @@ public void Validate_WhenStartAtIsAfterEndAt_ReturnsValidationResult() EndAt = DateTime.Now, CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, - Slug = "slug" + Slug = "slug", + Status = EventStatus.Completed }; var result = EventValidator.Validate(event1); @@ -151,7 +158,8 @@ public void Validate_WhenCreatedAtIsInTheFuture_ReturnsValidationResult() EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now.AddMinutes(1), UpdatedAt = DateTime.Now, - Slug = "slug" + Slug = "slug", + Status = EventStatus.Inprogress }; var result = EventValidator.Validate(event1); @@ -170,7 +178,8 @@ public void Validate_WhenUpdatedAtIsInTheFuture_ReturnsValidationResult() EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now.AddMinutes(1), - Slug = "slug" + Slug = "slug", + Status = EventStatus.WaitingForApproval }; var result = EventValidator.Validate(event1); @@ -189,7 +198,8 @@ public void Validate_WhenSlugIsEmpty_ReturnsValidationResult() EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, - Slug = "" + Slug = "", + Status = EventStatus.Inprogress }; var result = EventValidator.Validate(event1); @@ -209,7 +219,8 @@ public void Validate_WhenSlugIsTooLong_ReturnsValidationResult() EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, - Slug = new string('a', 129) + Slug = new string('a', 129), + Status = EventStatus.WaitingForApproval }; var result = EventValidator.Validate(event1); @@ -228,7 +239,8 @@ public void Validate_WhenSlugIsIsInvalid_ReturnsValidationResult() EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, - Slug = "invalid slug" + Slug = "invalid slug", + Status = EventStatus.Completed }; var result = EventValidator.Validate(event1); @@ -247,7 +259,8 @@ public void Validate_WhenSlugIsValid_ReturnsNoValidationResult() EndAt = DateTime.Now.AddMinutes(1), CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, - Slug = "valid-slug" + Slug = "valid-slug", + Status = EventStatus.Inprogress }; var result = EventValidator.Validate(event1); diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs index b1a3bd5c..1b7b2242 100644 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs @@ -9,7 +9,7 @@ public class InterestValidatorTests [TestMethod] public void Validate_WhenNameIsEmpty_ReturnsValidationResult() { - var interest = new IntrestDto + var interest = new InterestDto { Name = "" }; @@ -23,7 +23,7 @@ public void Validate_WhenNameIsEmpty_ReturnsValidationResult() [TestMethod] public void Validate_WhenNameIsTooLong_ReturnsValidationResult() { - var interest = new IntrestDto + var interest = new InterestDto { Name = new string('a', 33) }; @@ -36,7 +36,7 @@ public void Validate_WhenNameIsTooLong_ReturnsValidationResult() [TestMethod] public void Validate_WhenNameIsInvalid_ReturnsValidationResult() { - var interest = new IntrestDto + var interest = new InterestDto { Name = "Invalid Name" }; @@ -49,7 +49,7 @@ public void Validate_WhenNameIsInvalid_ReturnsValidationResult() [TestMethod] public void Validate_WhenNameIsValid_ReturnsNoValidationResult() { - var interest = new IntrestDto + var interest = new InterestDto { Name = "Valid Name" }; diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs deleted file mode 100644 index 80fb499a..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/ObjectTypeValidatorTests.cs +++ /dev/null @@ -1,62 +0,0 @@ -using ReasnAPI.Models.Database; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class ObjectTypeValidatorTests - { - [TestMethod] - public void Validate_WhenNameIsEmpty_ReturnsValidationResult() - { - var objectType = new ObjectType - { - Name = "" - }; - - var result = ObjectTypeValidator.Validate(objectType); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsInvalid_ReturnsValidationResult() - { - var objectType = new ObjectType - { - Name = "Invalid Name" - }; - - var result = ObjectTypeValidator.Validate(objectType); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsEvent_ReturnsNoValidationResult() - { - var objectType = new ObjectType - { - Name = "Event" - }; - - var result = ObjectTypeValidator.Validate(objectType); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenNameIsUser_ReturnsNoValidationResult() - { - var objectType = new ObjectType - { - Name = "User" - }; - - var result = ObjectTypeValidator.Validate(objectType); - - Assert.IsFalse(result.Any()); - } - } -} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs deleted file mode 100644 index 0509dbe1..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/RoleValidatorTests.cs +++ /dev/null @@ -1,75 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class RoleValidatorTests - { - [TestMethod] - public void Validate_WhenRoleNameIsEmpty_ReturnsValidationResult() - { - var role = new RoleDto - { - Name = "" - }; - - var result = RoleValidator.Validate(role); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Role name is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Role name is invalid")); - } - - [TestMethod] - public void Validate_WhenRoleNameIsInvalid_ReturnsValidationResult() - { - var role = new RoleDto - { - Name = "Invalid Role" - }; - - var result = RoleValidator.Validate(role); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Role name is invalid")); - } - - [TestMethod] - public void Validate_WhenRoleNameIsOrganizer_ReturnsNoValidationResult() - { - var role = new RoleDto - { - Name = "Organizer" - }; - - var result = RoleValidator.Validate(role); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenRoleNameIsAdmin_ReturnsNoValidationResult() - { - var role = new RoleDto - { - Name = "Admin" - }; - - var result = RoleValidator.Validate(role); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenRoleNameIsUser_ReturnsNoValidationResult() - { - var role = new RoleDto - { - Name = "User" - }; - - var result = RoleValidator.Validate(role); - - Assert.IsFalse(result.Any()); - } - } -} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs deleted file mode 100644 index 46a2b05b..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/StatusValidatorTests.cs +++ /dev/null @@ -1,101 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class StatusValidatorTests - { - [TestMethod] - public void Validate_WhenNameIsEmpty_ReturnsValidationResult() - { - var status = new StatusDto - { - Name = "" - }; - - var result = StatusValidator.Validate(status); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsInvalid_ReturnsValidationResult() - { - var status = new StatusDto - { - Name = "Invalid Name" - }; - - var result = StatusValidator.Validate(status); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsInterested_ReturnsValidationResult() - { - var status = new StatusDto - { - Name = "Interested" - }; - - var result = StatusValidator.Validate(status); - - Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsParticipating_ReturnsValidationResult() - { - var status = new StatusDto - { - Name = "Participating" - }; - - var result = StatusValidator.Validate(status); - - Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsCompleted_ReturnsValidationResult() - { - var status = new StatusDto - { - Name = "Completed" - }; - - var result = StatusValidator.Validate(status); - - Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsInProgress_ReturnsValidationResult() - { - var status = new StatusDto - { - Name = "In progress" - }; - - var result = StatusValidator.Validate(status); - - Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsWaitingForApproval_ReturnsValidationResult() - { - var status = new StatusDto - { - Name = "Waiting for approval" - }; - - var result = StatusValidator.Validate(status); - - Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - } -} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs index 47cea2a3..33aa6c54 100644 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs +++ b/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs @@ -1,4 +1,5 @@ using ReasnAPI.Models.DTOs; +using ReasnAPI.Models.Enums; using ReasnAPI.Validators; namespace ReasnAPI.Tests.Validators @@ -14,7 +15,7 @@ public void Validate_WhenNameIsEmpty_ReturnsValidationResult() Name = "", Surname = "Surname", Username = "Username", - RoleId = 1, + Role = UserRole.User, Email = "email@email.com", AddressId = 1, Phone = "+48 123456789" @@ -34,7 +35,7 @@ public void Validate_WhenNameIsTooLong_ReturnsValidationResult() Name = new string('a', 65), Surname = "Surname", Username = "Username", - RoleId = 1, + Role = UserRole.User, Email = "email@email.com", AddressId = 1, Phone = "+48 123456789" @@ -53,7 +54,7 @@ public void Validate_WhenNameIsInvalid_ReturnsValidationResult() Name = "Invalid Name", Surname = "Surname", Username = "Username", - RoleId = 1, + Role = UserRole.User, Email = "email@email.com", AddressId = 1, Phone = "+48 123456789" @@ -72,7 +73,7 @@ public void Validate_WhenNameIsValid_ReturnsNoValidationResult() Name = "Validname", Surname = "Surname", Username = "Username", - RoleId = 1, + Role = UserRole.User, Email = "email@email.com", AddressId = 1, Phone = "+48 123456789" @@ -91,7 +92,7 @@ public void Validate_WhenSurnameIsEmpty_ReturnsValidationResult() Name = "Name", Surname = "", Username = "Username", - RoleId = 1, + Role = UserRole.User, Email = "email@email.com", AddressId = 1, Phone = "+48 123456789" @@ -111,7 +112,7 @@ public void Validate_WhenSurnameIsTooLong_ReturnsValidationResult() Name = "Name", Surname = new string('a', 65), Username = "Username", - RoleId = 1, + Role = UserRole.User, Email = "email@email.com", AddressId = 1, Phone = "+48 123456789" @@ -130,7 +131,7 @@ public void Validate_WhenSurnameIsInvalid_ReturnsValidationResult() Name = "Name", Surname = "Invalid Surname", Username = "Username", - RoleId = 1, + Role = UserRole.User, Email = "email@email.com", AddressId = 1, Phone = "+48 123456789" @@ -149,7 +150,7 @@ public void Validate_WhenSurnameIsValid_ReturnsNoValidationResult() Name = "Name", Surname = "Validsurname", Username = "Username", - RoleId = 1, + Role = UserRole.User, Email = "email@email.com", AddressId = 1, Phone = "+48 123456789" @@ -168,7 +169,7 @@ public void Validate_WhenUsernameIsEmpty_ReturnsValidationResult() Name = "Name", Surname = "Surname", Username = "", - RoleId = 1, + Role = UserRole.User, Email = "email@email.com", AddressId = 1, Phone = "+48 123456789" @@ -188,7 +189,7 @@ public void Validate_WhenUsernameIsTooLong_ReturnsValidationResult() Name = "Name", Surname = "Surname", Username = new string('a', 65), - RoleId = 1, + Role = UserRole.User, Email = "email@email.com", AddressId = 1, Phone = "+48 123456789" @@ -207,7 +208,7 @@ public void Validate_WhenUsernameIsInvalid_ReturnsValidationResult() Name = "Name", Surname = "Surname", Username = "Invalid Username", - RoleId = 1, + Role = UserRole.User, Email = "email@email.com", AddressId = 1, Phone = "+48 123456789" @@ -226,7 +227,7 @@ public void Validate_WhenUsernameIsValid_ReturnsValidationResult() Name = "Name", Surname = "Surname", Username = "ValidUsername", - RoleId = 1, + Role = UserRole.User, Email = "email@email.com", AddressId = 1, Phone = "+48 123456789" @@ -245,7 +246,7 @@ public void Validate_WhenEmailIsEmpty_ReturnsValidationResult() Name = "Name", Surname = "Surname", Username = "Username", - RoleId = 1, + Role = UserRole.User, Email = "", AddressId = 1, Phone = "+48 123456789" @@ -265,7 +266,7 @@ public void Validate_WhenEmailIsTooLong_ReturnsValidationResult() Name = "Name", Surname = "Surname", Username = "Username", - RoleId = 1, + Role = UserRole.User, Email = new string('a', 256), AddressId = 1, Phone = "+48 123456789" @@ -284,7 +285,7 @@ public void Validate_WhenEmailIsInvalid_ReturnsValidationResult() Name = "Name", Surname = "Surname", Username = "Username", - RoleId = 1, + Role = UserRole.User, Email = "Invalid Email", AddressId = 1, Phone = "+48 123456789" @@ -303,7 +304,7 @@ public void Validate_WhenEmailIsValid_ReturnsNoValidationResult() Name = "Name", Surname = "Surname", Username = "Username", - RoleId = 1, + Role = UserRole.User, Email = "valid@email.com", AddressId = 1, Phone = "+48 123456789" @@ -322,7 +323,7 @@ public void Validate_WhenPhoneIsTooLong_ReturnsValidationResult() Name = "Name", Surname = "Surname", Username = "Username", - RoleId = 1, + Role = UserRole.User, Email = "email@email.com", AddressId = 1, Phone = new string('a', 20) @@ -341,7 +342,7 @@ public void Validate_WhenPhoneIsInvalid_ReturnsValidationResult() Name = "Name", Surname = "Surname", Username = "Username", - RoleId = 1, + Role = UserRole.User, Email = "email@email.com", AddressId = 1, Phone = "Invalid Phone" @@ -360,7 +361,7 @@ public void Validate_WhenPhoneIsValid_ReturnsNoValidationResult() Name = "Name", Surname = "Surname", Username = "Username", - RoleId = 1, + Role = UserRole.User, Email = "email@email.com", AddressId = 1, Phone = "+48 123456789" diff --git a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs index 85e31be5..d313de3f 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs @@ -10,7 +10,6 @@ public class EventValidator : IValidator private const int DescriptionMaxLength = 4048; private const int SlugMaxLength = 128; private const string SlugRegexPattern = "^[\\p{L}\\d]+[\\p{L}\\d-]*$"; - private const string StatusRegexPattern = "^(Completed|In progress|Approved|Waiting for aproval)$"; public static IEnumerable Validate(EventDto eventData) { @@ -63,11 +62,6 @@ public static IEnumerable Validate(EventDto eventData) { yield return new ValidationResult("Slug is invalid", [nameof(eventData.Name)]); } - - if (!new Regex(StatusRegexPattern).IsMatch(eventData.Status.ToString())) - { - yield return new ValidationResult("Status is invalid", [nameof(eventData.Status)]); - } } } } \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs deleted file mode 100644 index 5b3cda6f..00000000 --- a/Server/ReasnAPI/ReasnAPI/Validators/ImageValidator.cs +++ /dev/null @@ -1,19 +0,0 @@ -using ReasnAPI.Models.DTOs; -using System.ComponentModel.DataAnnotations; -using System.Text.RegularExpressions; - -namespace ReasnAPI.Validators -{ - public class ImageValidator : IValidator - { - private const string ObjectTypeRegexPattern = "^(Event|User)$"; - - public static IEnumerable Validate(ImageDto image) - { - if (!new Regex(ObjectTypeRegexPattern).IsMatch(image.ObjectType.ToString())) - { - yield return new ValidationResult("Object type is invalid", [nameof(image.ObjectType)]); - } - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ParticipantValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ParticipantValidator.cs deleted file mode 100644 index 6da0b100..00000000 --- a/Server/ReasnAPI/ReasnAPI/Validators/ParticipantValidator.cs +++ /dev/null @@ -1,19 +0,0 @@ -using ReasnAPI.Models.DTOs; -using System.ComponentModel.DataAnnotations; -using System.Text.RegularExpressions; - -namespace ReasnAPI.Validators -{ - public class ParticipantValidator : IValidator - { - private const string StatusRegexPattern = "^(Interested|Participating)$"; - - public static IEnumerable Validate(ParticipantDto participant) - { - if (!new Regex(StatusRegexPattern).IsMatch(participant.Status.ToString())) - { - yield return new ValidationResult("Status is invalid", [nameof(participant.Status)]); - } - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs index 2c830160..7d13bc16 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs @@ -16,7 +16,6 @@ public class UserValidator : IValidator private const string EmailRegexPattern = "^[a-zA-Z\\d._%+-]+@[a-zA-Z\\d.-]+\\.[a-zA-Z]{2,6}$"; private const int PhoneMaxLength = 16; private const string PhoneRegexPattern = "^\\+\\d{1,3}\\s\\d{1,15}$"; - private const string RoleRegexPattern = "^(Admin|User|Organizer)$"; public static IEnumerable Validate(UserDto user) { @@ -92,11 +91,6 @@ public static IEnumerable Validate(UserDto user) yield return new ValidationResult("Phone is invalid", [nameof(user.Phone)]); } } - - if (!new Regex(RoleRegexPattern).IsMatch(user.Role.ToString())) - { - yield return new ValidationResult("Role is invalid", [nameof(user.Role)]); - } } } } \ No newline at end of file From 30a86661159e1d2d43ace3e477a2473b0313a2b0 Mon Sep 17 00:00:00 2001 From: raczu Date: Sat, 1 Jun 2024 16:41:44 +0200 Subject: [PATCH 20/24] feat: add jwt and exceptions handlers Simplify the logic on the controllers' side, custom exceptions and a library for validation were added. The implemented handlers are allow to catch those exceptions and return the corresponding statuses and detailed response. Additionally, mappers have been created to more easily convert entities into the corresponding DTOs, fixed enum conversion when it comes to UserRole and export postgres port on the development environment. --- .../ReasnAPI/Common/IAssemblyMarker.cs | 6 ++ Server/ReasnAPI/ReasnAPI/Controllers/.gitkeep | 0 .../ReasnAPI/Controllers/AuthController.cs | 49 ++++++++++ .../ReasnAPI/Controllers/UsersController.cs | 15 +++ .../Exceptions/ServiceExceptionHandler.cs | 58 ++++++++++++ .../Exceptions/ValidationExceptionHandler.cs | 49 ++++++++++ .../ReasnAPI/Mappers/AddressMapper.cs | 23 +++++ .../ReasnAPI/Mappers/InterestMapper.cs | 20 ++++ .../ReasnAPI/Mappers/UserInterestMapper.cs | 21 +++++ .../ReasnAPI/ReasnAPI/Mappers/UserMapper.cs | 27 ++++++ .../Models/Authentication/LoginRequest.cs | 7 ++ .../Models/Authentication/RegisterRequest.cs | 18 ++++ .../Models/Authentication/TokenPayload.cs | 8 ++ .../ReasnAPI/Models/DTOs/AddressDto.cs | 4 +- .../ReasnAPI/Models/Database/ReasnContext.cs | 28 ++---- .../ReasnAPI/Models/Enums/UserRole.cs | 9 +- Server/ReasnAPI/ReasnAPI/Program.cs | 93 ++++++++++++++++--- Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj | 12 +-- Server/ReasnAPI/ReasnAPI/Services/.gitkeep | 0 .../Services/Authentication/AuthService.cs | 79 ++++++++++++++++ .../Services/Authentication/TokenService.cs | 53 +++++++++++ .../Exceptions/BadRequestException.cs | 10 ++ .../Services/Exceptions/NotFoundException.cs | 10 ++ .../Exceptions/VerificationException.cs | 10 ++ Server/ReasnAPI/ReasnAPI/Validators/.gitkeep | 0 .../ReasnAPI/Validators/AddressValidator.cs | 36 +++++++ .../Authentication/LoginRequestValidator.cs | 18 ++++ .../RegisterRequestValidator.cs | 53 +++++++++++ Server/ReasnAPI/ReasnAPI/appsettings.json | 16 ++-- compose.override.yml | 4 +- 30 files changed, 683 insertions(+), 53 deletions(-) create mode 100644 Server/ReasnAPI/ReasnAPI/Common/IAssemblyMarker.cs delete mode 100644 Server/ReasnAPI/ReasnAPI/Controllers/.gitkeep create mode 100644 Server/ReasnAPI/ReasnAPI/Controllers/AuthController.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Controllers/UsersController.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Exceptions/ServiceExceptionHandler.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Exceptions/ValidationExceptionHandler.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Mappers/AddressMapper.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Mappers/InterestMapper.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Mappers/UserInterestMapper.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Mappers/UserMapper.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Models/Authentication/LoginRequest.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Models/Authentication/RegisterRequest.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Models/Authentication/TokenPayload.cs delete mode 100644 Server/ReasnAPI/ReasnAPI/Services/.gitkeep create mode 100644 Server/ReasnAPI/ReasnAPI/Services/Authentication/AuthService.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Services/Authentication/TokenService.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Services/Exceptions/BadRequestException.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Services/Exceptions/NotFoundException.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Services/Exceptions/VerificationException.cs delete mode 100644 Server/ReasnAPI/ReasnAPI/Validators/.gitkeep create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/Authentication/LoginRequestValidator.cs create mode 100644 Server/ReasnAPI/ReasnAPI/Validators/Authentication/RegisterRequestValidator.cs diff --git a/Server/ReasnAPI/ReasnAPI/Common/IAssemblyMarker.cs b/Server/ReasnAPI/ReasnAPI/Common/IAssemblyMarker.cs new file mode 100644 index 00000000..1031a093 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Common/IAssemblyMarker.cs @@ -0,0 +1,6 @@ +namespace ReasnAPI.Validators; + +public interface IAssemblyMarker +{ + +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Controllers/.gitkeep b/Server/ReasnAPI/ReasnAPI/Controllers/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/Server/ReasnAPI/ReasnAPI/Controllers/AuthController.cs b/Server/ReasnAPI/ReasnAPI/Controllers/AuthController.cs new file mode 100644 index 00000000..9342a620 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Controllers/AuthController.cs @@ -0,0 +1,49 @@ +using FluentValidation; +using Microsoft.AspNetCore.Mvc; +using ReasnAPI.Mappers; +using ReasnAPI.Models.Authentication; +using ReasnAPI.Services.Authentication; + +namespace ReasnAPI.Controllers; + +[ApiController] +[Route("api/[controller]")] +public class AuthController : ControllerBase +{ + private readonly AuthService _authService; + private readonly TokenService _tokenService; + + public AuthController(AuthService authService, TokenService tokenService) + { + _authService = authService; + _tokenService = tokenService; + } + + [HttpPost("login")] + public IActionResult Login( + [FromBody] LoginRequest request, + [FromServices] IValidator validator) + { + validator.ValidateAndThrow(request); + var user = _authService.Login(request); + + var tokenPayload = _tokenService.GenerateToken(user); + return Ok(tokenPayload); + } + + [HttpPost("register")] + public IActionResult Register( + [FromBody] RegisterRequest request, + [FromServices] IValidator validator) + { + validator.ValidateAndThrow(request); + var user = _authService.Register(request); + + var location = Url.Action( + action: nameof(UsersController.GetUserByUsername), + controller: "Users", + values: new { username = user.Username }); + + return Created(location, user.ToDto()); + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Controllers/UsersController.cs b/Server/ReasnAPI/ReasnAPI/Controllers/UsersController.cs new file mode 100644 index 00000000..0904a8bf --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Controllers/UsersController.cs @@ -0,0 +1,15 @@ +using Microsoft.AspNetCore.Mvc; + +namespace ReasnAPI.Controllers; + +[ApiController] +[Route("api/[controller]")] +public class UsersController : ControllerBase +{ + [HttpGet] + [Route("{username}")] + public IActionResult GetUserByUsername(string username) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Exceptions/ServiceExceptionHandler.cs b/Server/ReasnAPI/ReasnAPI/Exceptions/ServiceExceptionHandler.cs new file mode 100644 index 00000000..5a710393 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Exceptions/ServiceExceptionHandler.cs @@ -0,0 +1,58 @@ +using System.Net; +using Microsoft.AspNetCore.Diagnostics; +using Microsoft.AspNetCore.Mvc; +using ReasnAPI.Services.Exceptions; + +namespace ReasnAPI.Exceptions; + +public class ServiceExceptionHandler : IExceptionHandler +{ + private readonly IProblemDetailsService _problemDetailsService; + + public ServiceExceptionHandler(IProblemDetailsService problemDetailsService) + { + _problemDetailsService = problemDetailsService; + } + + public async ValueTask TryHandleAsync( + HttpContext httpContext, + Exception exception, + CancellationToken cancellationToken) + { + var problemDetails = new ProblemDetails + { + Detail = exception.Message + }; + + switch (exception) + { + case BadRequestException: + httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; + problemDetails.Type = "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.1"; + problemDetails.Title = "A bad request was made"; + break; + + case NotFoundException: + httpContext.Response.StatusCode = (int)HttpStatusCode.NotFound; + problemDetails.Type = "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.4"; + problemDetails.Title = "A resource was not found"; + break; + + case VerificationException: + httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; + problemDetails.Type = "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.1"; + problemDetails.Title = "A verification error occurred"; + break; + + default: + return false; + } + + return await _problemDetailsService.TryWriteAsync(new ProblemDetailsContext + { + HttpContext = httpContext, + ProblemDetails = problemDetails, + Exception = exception + }); + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Exceptions/ValidationExceptionHandler.cs b/Server/ReasnAPI/ReasnAPI/Exceptions/ValidationExceptionHandler.cs new file mode 100644 index 00000000..296415d1 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Exceptions/ValidationExceptionHandler.cs @@ -0,0 +1,49 @@ +using System.Net; +using FluentValidation; +using Microsoft.AspNetCore.Diagnostics; + +namespace ReasnAPI.Exceptions; + +public class ValidationExceptionHandler : IExceptionHandler +{ + private readonly IProblemDetailsService _problemDetailsService; + + public ValidationExceptionHandler(IProblemDetailsService problemDetailsService) + { + _problemDetailsService = problemDetailsService; + } + + public async ValueTask TryHandleAsync( + HttpContext httpContext, + Exception exception, + CancellationToken cancellationToken) + { + if (exception is not ValidationException validationException) + { + return false; + } + + var errors = validationException.Errors.Select(e => new + { + field = e.PropertyName, + message = e.ErrorMessage + }).ToList(); + + httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; + return await _problemDetailsService.TryWriteAsync(new ProblemDetailsContext + { + HttpContext = httpContext, + ProblemDetails = + { + Title = "A validation error occurred", + Detail = "One or more validation errors occurred", + Type = "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.1", + Extensions = + { + ["errors"] = errors + } + }, + Exception = validationException + }); + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Mappers/AddressMapper.cs b/Server/ReasnAPI/ReasnAPI/Mappers/AddressMapper.cs new file mode 100644 index 00000000..e4ef17a1 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Mappers/AddressMapper.cs @@ -0,0 +1,23 @@ +using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; + +namespace ReasnAPI.Mappers; + +public static class AddressMapper +{ + public static AddressDto ToDto(this Address address) + { + return new AddressDto + { + Street = address.Street, + City = address.City, + State = address.State, + ZipCode = address.ZipCode + }; + } + + public static List ToDtoList(this IEnumerable
addresses) + { + return addresses.Select(ToDto).ToList(); + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Mappers/InterestMapper.cs b/Server/ReasnAPI/ReasnAPI/Mappers/InterestMapper.cs new file mode 100644 index 00000000..1ea23dd2 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Mappers/InterestMapper.cs @@ -0,0 +1,20 @@ +using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; + +namespace ReasnAPI.Mappers; + +public static class InterestMapper +{ + public static InterestDto ToDto(this Interest interest) + { + return new InterestDto + { + Name = interest.Name + }; + } + + public static List ToDtoList(this IEnumerable interests) + { + return interests.Select(ToDto).ToList(); + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Mappers/UserInterestMapper.cs b/Server/ReasnAPI/ReasnAPI/Mappers/UserInterestMapper.cs new file mode 100644 index 00000000..a4f1f831 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Mappers/UserInterestMapper.cs @@ -0,0 +1,21 @@ +using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; + +namespace ReasnAPI.Mappers; + +public static class UserInterestMapper +{ + public static UserInterestDto ToDto(this UserInterest userInterest) + { + return new UserInterestDto + { + Interest = userInterest.Interest.ToDto(), + Level = userInterest.Level + }; + } + + public static List ToDtoList(this IEnumerable userInterests) + { + return userInterests.Select(ToDto).ToList(); + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Mappers/UserMapper.cs b/Server/ReasnAPI/ReasnAPI/Mappers/UserMapper.cs new file mode 100644 index 00000000..512756b8 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Mappers/UserMapper.cs @@ -0,0 +1,27 @@ +using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; + +namespace ReasnAPI.Mappers; + +public static class UserMapper +{ + public static UserDto ToDto(this User user) + { + return new UserDto + { + Username = user.Username, + Name = user.Name, + Surname = user.Surname, + Email = user.Email, + Phone = user.Phone, + Role = user.Role, + AddressId = user.AddressId, + Interests = user.UserInterests.ToDtoList() + }; + } + + public static List ToDtoList(this IEnumerable users) + { + return users.Select(ToDto).ToList(); + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Models/Authentication/LoginRequest.cs b/Server/ReasnAPI/ReasnAPI/Models/Authentication/LoginRequest.cs new file mode 100644 index 00000000..addc4f34 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Models/Authentication/LoginRequest.cs @@ -0,0 +1,7 @@ +namespace ReasnAPI.Models.Authentication; + +public class LoginRequest +{ + public string Email { get; set; } = null!; + public string Password { get; set; } = null!; +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Models/Authentication/RegisterRequest.cs b/Server/ReasnAPI/ReasnAPI/Models/Authentication/RegisterRequest.cs new file mode 100644 index 00000000..59dae251 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Models/Authentication/RegisterRequest.cs @@ -0,0 +1,18 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Models.Enums; + +namespace ReasnAPI.Models.Authentication; + +public class RegisterRequest +{ + public string Name { get; set; } = null!; + public string Surname { get; set; } = null!; + public string Email { get; set; } = null!; + public string Username { get; set; } = null!; + public string Password { get; set; } = null!; + + public string? Phone { get; set; } + + public AddressDto Address { get; set; } = null!; + public string Role { get; set; } = null!; +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Models/Authentication/TokenPayload.cs b/Server/ReasnAPI/ReasnAPI/Models/Authentication/TokenPayload.cs new file mode 100644 index 00000000..118726d6 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Models/Authentication/TokenPayload.cs @@ -0,0 +1,8 @@ +namespace ReasnAPI.Models.Authentication; + +public class TokenPayload +{ + public string TokenType { get; set; } + public string AccessToken { get; set; } + public int ExpiresIn { get; set; } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Models/DTOs/AddressDto.cs b/Server/ReasnAPI/ReasnAPI/Models/DTOs/AddressDto.cs index 1500dfaa..2ce72d41 100644 --- a/Server/ReasnAPI/ReasnAPI/Models/DTOs/AddressDto.cs +++ b/Server/ReasnAPI/ReasnAPI/Models/DTOs/AddressDto.cs @@ -1,6 +1,6 @@ -namespace ReasnAPI.Models.DTOs +namespace ReasnAPI.Models.DTOs { - public class AddressDto + public class AddressDto { public string Country { get; set; } = null!; public string City { get; set; } = null!; diff --git a/Server/ReasnAPI/ReasnAPI/Models/Database/ReasnContext.cs b/Server/ReasnAPI/ReasnAPI/Models/Database/ReasnContext.cs index 041cf80b..4e821038 100644 --- a/Server/ReasnAPI/ReasnAPI/Models/Database/ReasnContext.cs +++ b/Server/ReasnAPI/ReasnAPI/Models/Database/ReasnContext.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using ReasnAPI.Models.Enums; namespace ReasnAPI.Models.Database; @@ -37,7 +38,12 @@ public ReasnContext(DbContextOptions options) public virtual DbSet UserInterests { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - => optionsBuilder.UseNpgsql("name=ConnectionStrings:DefaultValue"); + { + if (!optionsBuilder.IsConfigured) + { + optionsBuilder.UseNpgsql("name=ConnectionStrings:DefaultValue"); + } + } protected override void OnModelCreating(ModelBuilder modelBuilder) { @@ -47,26 +53,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasPostgresEnum("common", "participant_status", new[] { "Interested", "Participating" }) .HasPostgresEnum("users", "role", new[] { "User", "Organizer", "Admin" }); - modelBuilder - .Entity() - .Property(u => u.Role) - .HasConversion(); - - modelBuilder - .Entity() - .Property(u => u.Status) - .HasConversion(); - - modelBuilder - .Entity() - .Property(u => u.ObjectType) - .HasConversion (); - - modelBuilder - .Entity() - .Property(u => u.Status) - .HasConversion(); - modelBuilder.Entity
(entity => { entity.HasKey(e => e.Id).HasName("address_pkey"); diff --git a/Server/ReasnAPI/ReasnAPI/Models/Enums/UserRole.cs b/Server/ReasnAPI/ReasnAPI/Models/Enums/UserRole.cs index 4a35be42..fb13bf68 100644 --- a/Server/ReasnAPI/ReasnAPI/Models/Enums/UserRole.cs +++ b/Server/ReasnAPI/ReasnAPI/Models/Enums/UserRole.cs @@ -1,8 +1,15 @@ -namespace ReasnAPI.Models.Enums; +using NpgsqlTypes; + +namespace ReasnAPI.Models.Enums; public enum UserRole { + [PgName("User")] User, + + [PgName("Organizer")] Organizer, + + [PgName("Admin")] Admin } \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Program.cs b/Server/ReasnAPI/ReasnAPI/Program.cs index 67d181aa..4bb3484c 100644 --- a/Server/ReasnAPI/ReasnAPI/Program.cs +++ b/Server/ReasnAPI/ReasnAPI/Program.cs @@ -1,26 +1,69 @@ using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Options; using Microsoft.OpenApi.Models; using Npgsql; using ReasnAPI.Models.Enums; using Serilog; -using System; +using System.Text; using System.Text.Json.Serialization; +using FluentValidation; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.IdentityModel.Tokens; +using ReasnAPI.Exceptions; using ReasnAPI.Models.Database; +using ReasnAPI.Services.Authentication; +using ReasnAPI.Validators; var builder = WebApplication.CreateSlimBuilder(args); +var config = builder.Configuration; -builder.Services.AddControllers(); -var dataSourceBuilder = new NpgsqlDataSourceBuilder(builder.Configuration.GetConnectionString("DefaultValue")); -dataSourceBuilder.MapEnum("events.participant.status"); -dataSourceBuilder.MapEnum("events.event.status"); -dataSourceBuilder.MapEnum("common.image.object_type"); -dataSourceBuilder.MapEnum("users.user.role"); +builder.Services.AddAuthentication(options => +{ + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; +}).AddJwtBearer(jwt => +{ + jwt.TokenValidationParameters = new TokenValidationParameters + { + ValidIssuer = config["JwtSettings:Issuer"], + ValidAudiences = config.GetSection("JwtSettings:Audiences").Get>(), + IssuerSigningKey = new SymmetricSecurityKey + (Encoding.UTF8.GetBytes(config["JwtSettings:Key"]!)), + ValidateIssuer = true, + ValidateAudience = true, + ValidateLifetime = true, + ValidateIssuerSigningKey = true + }; +}); + +builder.Services.AddExceptionHandler(); +builder.Services.AddExceptionHandler(); +builder.Services.AddProblemDetails(options => + options.CustomizeProblemDetails = ctx => + { + ctx.ProblemDetails.Instance = $"{ctx.HttpContext.Request.Method} {ctx.HttpContext.Request.Path}"; + }); + +builder.Services.AddControllers() + .AddJsonOptions(options => + { + options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); + }); + +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddValidatorsFromAssemblyContaining(); + +var dataSourceBuilder = new NpgsqlDataSourceBuilder(config.GetConnectionString("DefaultValue")); +dataSourceBuilder.MapEnum("common.participant_status"); +dataSourceBuilder.MapEnum("common.event_status"); +dataSourceBuilder.MapEnum("common.object_type"); +dataSourceBuilder.MapEnum("users.role"); var dataSource = dataSourceBuilder.Build(); -// todo: uncomment after creating DbContext and change context name and if needed - connection string localized in appsettings.json builder.Services.AddDbContext(options => - options.UseNpgsql(dataSource)); + options.UseNpgsql(dataSource) + .EnableDetailedErrors()); builder.Services.AddSwaggerGen(options => { @@ -29,10 +72,32 @@ Version = "v1", Title = "Reasn API" }); + options.AddSecurityDefinition("JWT", new OpenApiSecurityScheme + { + Description = "JWT Authorization header using the Bearer scheme.", + Name = "Authorization", + In = ParameterLocation.Header, + Type = SecuritySchemeType.ApiKey, + Scheme = "Bearer" + }); + options.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "JWT" + } + }, + Array.Empty() + } + }); }); Log.Logger = new LoggerConfiguration() - .ReadFrom.Configuration(builder.Configuration).CreateLogger(); + .ReadFrom.Configuration(config).CreateLogger(); builder.Host.UseSerilog(); @@ -47,10 +112,16 @@ }); } +app.UseExceptionHandler(); +app.UseStatusCodePages(); + app.UseSerilogRequestLogging(); app.UseHttpsRedirection(); +app.UseAuthentication(); +app.UseAuthorization(); + app.MapSwagger(); app.MapControllers(); diff --git a/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj b/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj index 23499ae8..312bd617 100644 --- a/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj +++ b/Server/ReasnAPI/ReasnAPI/ReasnAPI.csproj @@ -9,23 +9,17 @@ + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - - - - - - - - diff --git a/Server/ReasnAPI/ReasnAPI/Services/.gitkeep b/Server/ReasnAPI/ReasnAPI/Services/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/Server/ReasnAPI/ReasnAPI/Services/Authentication/AuthService.cs b/Server/ReasnAPI/ReasnAPI/Services/Authentication/AuthService.cs new file mode 100644 index 00000000..5231ce8d --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Services/Authentication/AuthService.cs @@ -0,0 +1,79 @@ +using Microsoft.AspNetCore.Identity; +using Microsoft.EntityFrameworkCore; +using ReasnAPI.Models.Authentication; +using ReasnAPI.Models.Database; +using ReasnAPI.Models.Enums; +using ReasnAPI.Services.Exceptions; + +namespace ReasnAPI.Services.Authentication; + +public class AuthService +{ + private readonly ReasnContext _context; + private readonly PasswordHasher _hasher; + + public AuthService(ReasnContext context) + { + _context = context; + _hasher = new PasswordHasher(); + } + + public User Login(LoginRequest request) + { + var user = _context.Users.FirstOrDefault(u => + EF.Functions.ILike(u.Email, request.Email)); + + if (user is null) + { + throw new NotFoundException("Not found user related with provided email"); + } + + var result = _hasher.VerifyHashedPassword( + user, user.Password, request.Password); + + if (result != PasswordVerificationResult.Success) + { + throw new VerificationException("Provided password is incorrect"); + } + + return user; + } + + public User Register(RegisterRequest request) + { + var userAlreadyExists = _context.Users.Any(u => + EF.Functions.ILike(u.Email, request.Email) || + EF.Functions.ILike(u.Username, request.Username)); + + if (userAlreadyExists) + { + throw new BadRequestException( + "User with provided email or username already exists"); + } + + var user = new User + { + Name = request.Name, + Surname = request.Surname, + Email = request.Email, + Username = request.Username, + Role = Enum.Parse(request.Role), + IsActive = true, + CreatedAt = DateTime.UtcNow, + UpdatedAt = DateTime.UtcNow, + Address = new Address + { + Country = request.Address.Country, + City = request.Address.City, + Street = request.Address.Street, + State = request.Address.State, + } + }; + _context.Users.Add(user); + + user.Password = _hasher.HashPassword(user, request.Password); + _context.SaveChanges(); + + return user; + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Services/Authentication/TokenService.cs b/Server/ReasnAPI/ReasnAPI/Services/Authentication/TokenService.cs new file mode 100644 index 00000000..87d4e519 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Services/Authentication/TokenService.cs @@ -0,0 +1,53 @@ +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; +using Microsoft.IdentityModel.Tokens; +using ReasnAPI.Models.Authentication; +using ReasnAPI.Models.Database; + +namespace ReasnAPI.Services.Authentication; + +public class TokenService +{ + private readonly IConfiguration _configuration; + + public TokenService(IConfiguration configuration) => + _configuration = configuration; + + public TokenPayload GenerateToken(User user) + { + var tokenHandler = new JwtSecurityTokenHandler(); + var tokenLifetime = TimeSpan.FromHours( + _configuration.GetValue("JwtSettings:DurationInHours")); + + var key = Encoding.UTF8.GetBytes(_configuration["JwtSettings:Key"]!); + var issuer = _configuration["JwtSettings:Issuer"]!; + var audiences = _configuration.GetSection("JwtSettings:Audiences") + .Get>()!; + + var tokenDescriptor = new SecurityTokenDescriptor + { + Subject = new ClaimsIdentity(new [] + { + new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), + new Claim(JwtRegisteredClaimNames.Sub, user.Email), + new Claim(JwtRegisteredClaimNames.Email, user.Email), + new Claim(ClaimTypes.Role, user.Role.ToString()), + new Claim(JwtRegisteredClaimNames.Iss, issuer), + new Claim(JwtRegisteredClaimNames.Aud, string.Join(",", audiences)) + }), + Expires = DateTime.UtcNow.Add(tokenLifetime), + SigningCredentials = new SigningCredentials( + new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256) + }; + + var token = tokenHandler.CreateToken(tokenDescriptor); + var tokenPayload = new TokenPayload + { + TokenType = "Bearer", + AccessToken = tokenHandler.WriteToken(token), + ExpiresIn = Convert.ToInt32(tokenLifetime.TotalSeconds) + }; + return tokenPayload; + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Services/Exceptions/BadRequestException.cs b/Server/ReasnAPI/ReasnAPI/Services/Exceptions/BadRequestException.cs new file mode 100644 index 00000000..2e8af887 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Services/Exceptions/BadRequestException.cs @@ -0,0 +1,10 @@ +namespace ReasnAPI.Services.Exceptions; + +public class BadRequestException : Exception +{ + public BadRequestException() { } + + public BadRequestException(string message) : base(message) { } + + public BadRequestException(string message, Exception inner) : base(message, inner) { } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Services/Exceptions/NotFoundException.cs b/Server/ReasnAPI/ReasnAPI/Services/Exceptions/NotFoundException.cs new file mode 100644 index 00000000..90ecb02a --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Services/Exceptions/NotFoundException.cs @@ -0,0 +1,10 @@ +namespace ReasnAPI.Services.Exceptions; + +public class NotFoundException : Exception +{ + public NotFoundException() { } + + public NotFoundException(string message) : base(message) { } + + public NotFoundException(string message, Exception inner) : base(message, inner) { } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Services/Exceptions/VerificationException.cs b/Server/ReasnAPI/ReasnAPI/Services/Exceptions/VerificationException.cs new file mode 100644 index 00000000..97525c39 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Services/Exceptions/VerificationException.cs @@ -0,0 +1,10 @@ +namespace ReasnAPI.Services.Exceptions; + +public class VerificationException : Exception +{ + public VerificationException() { } + + public VerificationException(string message) : base(message) { } + + public VerificationException(string message, Exception inner) : base(message, inner) { } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/.gitkeep b/Server/ReasnAPI/ReasnAPI/Validators/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs new file mode 100644 index 00000000..93ef57ac --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs @@ -0,0 +1,36 @@ +using FluentValidation; +using Microsoft.VisualBasic; +using ReasnAPI.Models.DTOs; + +namespace ReasnAPI.Validators; + +public class AddressValidator : AbstractValidator +{ + public AddressValidator() + { + RuleFor(r => r.Country) + .NotEmpty() + .MaximumLength(64) + .Matches(@"^\p{Lu}\p{Ll}+(?:(\s|-)(\p{Lu}\p{Ll}+|i|of|and|the)){0,5}$"); + + RuleFor(r => r.City) + .NotEmpty() + .MaximumLength(64) + .Matches(@"^\p{Lu}\p{Ll}+(?:(\s|-)\p{Lu}\p{Ll}+)*$"); + + RuleFor(r => r.Street) + .NotEmpty() + .MaximumLength(64) + .Matches(@"^[\p{L}\d]+(?:(\s)\p{L}+)*(\s(?:(\d+\p{L}?(/\d*\p{L}?)?)))?$"); + + RuleFor(r => r.State) + .NotEmpty() + .MaximumLength(64) + .Matches(@"^\p{Lu}\p{Ll}+(?:(\s|-)\p{L}+)*$"); + + RuleFor(r => r.ZipCode) + .MaximumLength(8) + .Matches(@"^[\p{L}\d\s-]{3,}$") + .When(r => !string.IsNullOrEmpty(r.ZipCode)); + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/Authentication/LoginRequestValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/Authentication/LoginRequestValidator.cs new file mode 100644 index 00000000..3b85c79d --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/Authentication/LoginRequestValidator.cs @@ -0,0 +1,18 @@ +using FluentValidation; +using ReasnAPI.Models.Authentication; + +namespace ReasnAPI.Validators.Authentication; + +public class LoginRequestValidator : AbstractValidator +{ + public LoginRequestValidator() + { + RuleFor(r => r.Email) + .NotEmpty() + .EmailAddress() + .WithMessage("Email is not in expected format"); + + RuleFor(r => r.Password) + .NotEmpty(); + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/Authentication/RegisterRequestValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/Authentication/RegisterRequestValidator.cs new file mode 100644 index 00000000..7b82e0cc --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI/Validators/Authentication/RegisterRequestValidator.cs @@ -0,0 +1,53 @@ +using FluentValidation; +using ReasnAPI.Models.Authentication; +using ReasnAPI.Models.Enums; + +namespace ReasnAPI.Validators.Authentication; + +public class RegisterRequestValidator : AbstractValidator +{ + public RegisterRequestValidator() + { + RuleFor(r => r.Name) + .NotEmpty() + .MaximumLength(64) + .Matches(@"^\p{Lu}\p{Ll}+$"); + + RuleFor(r => r.Surname) + .NotEmpty() + .MaximumLength(64) + .Matches(@"^\p{L}+(?:[\s'-]?\p{L}+)*$"); + + RuleFor(r => r.Username) + .NotEmpty() + .MaximumLength(64) + .Matches(@"^[\p{L}\d._%+-]+$"); + + RuleFor(r => r.Email) + .NotEmpty() + .MaximumLength(255) + .EmailAddress() + .WithMessage("Email is not in expected format"); + + RuleFor(r => r.Password) + .NotEmpty() + .Matches(@"^((?=\S*?[A-Z])(?=\S*?[a-z])(?=\S*?[0-9]).{6,})\S$") + .WithMessage( + "Password must contain at least one uppercase letter, " + + "one lowercase letter, one number, and be at least 6 characters long"); + + RuleFor(r => r.Phone) + .Matches(@"^\+\d{1,3}\s\d{1,15}$") + .When(r => !string.IsNullOrEmpty(r.Phone)) + .WithMessage("Phone number is not in expected format"); + + RuleFor(r => r.Address) + .NotNull() + .SetValidator(new AddressValidator()); + + RuleFor(r => r.Role) + .NotEmpty() + .Must(r => r == UserRole.User.ToString() || r == UserRole.Organizer.ToString()) + .WithMessage($"Role must be either '{UserRole.User.ToString()}' or '{UserRole.Organizer.ToString()}'"); + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/appsettings.json b/Server/ReasnAPI/ReasnAPI/appsettings.json index 826f8080..58588f6e 100644 --- a/Server/ReasnAPI/ReasnAPI/appsettings.json +++ b/Server/ReasnAPI/ReasnAPI/appsettings.json @@ -2,21 +2,21 @@ "Serilog": { "Using": [ "Serilog.Sinks.Console" - //"Serilog.Sinks.File" ], "WriteTo": [ { "Name": "Console" } - //{ - // "Name": "File", - // "Args": { - // "path": "logs/ReasnAPI-.log", - // "rollingInterval": "Day" - // } - //} ] }, "ConnectionStrings": { "DefaultValue": "Server=postgres;Port=5432;Database=reasn;User Id=dba;Password=sql;" }, + "JwtSettings": { + "Issuer": "http://localhost:5272", + "Audiences": [ + "http://localhost:5272" + ], + "Key": "YOUR_SECRET_KEY", + "DurationInHours": 8 + }, "AllowedHosts": "*" } diff --git a/compose.override.yml b/compose.override.yml index 78ce04ea..17c93175 100644 --- a/compose.override.yml +++ b/compose.override.yml @@ -47,6 +47,8 @@ services: path: ./Server/ReasnAPI/ReasnAPI postgres: + ports: + - "5432:5432" volumes: - ./Database/init-dev-data.sql:/docker-entrypoint-initdb.d/03-init-dev-data.sql - \ No newline at end of file + From 14e3333b291fe52d6753991d4f63b55aaa75d5bc Mon Sep 17 00:00:00 2001 From: raczu Date: Sat, 1 Jun 2024 20:56:45 +0200 Subject: [PATCH 21/24] test: add unit tests for jwt, handlers and validators --- .../ReasnAPI.Tests/ReasnAPI.Tests.csproj | 5 + Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs | 12 - .../ServiceExceptionHandlerTests.cs | 93 ++++++ .../ValidationExceptionHandlerTests.cs | 54 ++++ .../Authentication/AuthServiceTests.cs | 125 ++++++++ .../Authentication/TokenServiceTests.cs | 82 ++++++ .../Validators/AddressValidatorTests.cs | 205 +++++++++++++ .../LoginRequestValidatorTests.cs | 62 ++++ .../RegisterRequestValidatorTests.cs | 278 ++++++++++++++++++ .../Models/Authentication/RegisterRequest.cs | 3 - .../Services/Authentication/AuthService.cs | 6 +- .../Authentication/LoginRequestValidator.cs | 3 +- .../RegisterRequestValidator.cs | 16 +- 13 files changed, 915 insertions(+), 29 deletions(-) delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Exceptions/ServiceExceptionHandlerTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Exceptions/ValidationExceptionHandlerTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Services/Authentication/AuthServiceTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Services/Authentication/TokenServiceTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/AddressValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/Authentication/LoginRequestValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/Authentication/RegisterRequestValidatorTests.cs diff --git a/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj b/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj index 1b46a3ed..852b4685 100644 --- a/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj +++ b/Server/ReasnAPI/ReasnAPI.Tests/ReasnAPI.Tests.csproj @@ -13,10 +13,15 @@ + + + + + diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs deleted file mode 100644 index 46dac6f2..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/UnitTest1.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace ReasnAPI.Tests -{ - [TestClass] - public class UnitTest1 - { - [TestMethod] - public void TestAdd() - { - Assert.AreEqual(17, 17); - } - } -} diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Exceptions/ServiceExceptionHandlerTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Exceptions/ServiceExceptionHandlerTests.cs new file mode 100644 index 00000000..c2f31712 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Exceptions/ServiceExceptionHandlerTests.cs @@ -0,0 +1,93 @@ +using System.Net; +using Microsoft.AspNetCore.Http; +using Moq; +using ReasnAPI.Exceptions; +using ReasnAPI.Services.Exceptions; + +namespace ReasnAPI.Tests.UnitTests.Exceptions; + +[TestClass] +public class ServiceExceptionHandlerTests +{ + private Mock _mockProblemDetailsService = null!; + private ServiceExceptionHandler _handler = null!; + + [TestInitialize] + public void Setup() + { + _mockProblemDetailsService = new Mock(); + _handler = new ServiceExceptionHandler(_mockProblemDetailsService.Object); + } + + [TestMethod] + public async Task HandleException_WhenBadRequestException_ShouldReturnProblemDetails() + { + var httpContext = new DefaultHttpContext(); + var exception = new BadRequestException("Bad request"); + + ProblemDetailsContext? problemDetailsContext = null; + _mockProblemDetailsService.Setup(x => + x.TryWriteAsync(It.IsAny())) + .Callback(context => problemDetailsContext = context) + .ReturnsAsync(true); + + await _handler.TryHandleAsync(httpContext, exception, CancellationToken.None); + + Assert.AreEqual((int)HttpStatusCode.BadRequest, httpContext.Response.StatusCode); + Assert.IsNotNull(problemDetailsContext); + Assert.AreEqual("https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.1", + problemDetailsContext.ProblemDetails.Type); + Assert.AreEqual("A bad request was made", + problemDetailsContext.ProblemDetails.Title); + Assert.AreEqual(exception, problemDetailsContext.Exception); + Assert.AreEqual(exception.Message, problemDetailsContext.ProblemDetails.Detail); + } + + [TestMethod] + public async Task HandleException_WhenNotFoundException_ShouldReturnProblemDetails() + { + var httpContext = new DefaultHttpContext(); + var exception = new NotFoundException("Resource not found"); + + ProblemDetailsContext? problemDetailsContext = null; + _mockProblemDetailsService.Setup(x => + x.TryWriteAsync(It.IsAny())) + .Callback(context => problemDetailsContext = context) + .ReturnsAsync(true); + + await _handler.TryHandleAsync(httpContext, exception, CancellationToken.None); + + Assert.AreEqual((int)HttpStatusCode.NotFound, httpContext.Response.StatusCode); + Assert.IsNotNull(problemDetailsContext); + Assert.AreEqual("https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.4", + problemDetailsContext.ProblemDetails.Type); + Assert.AreEqual("A resource was not found", + problemDetailsContext.ProblemDetails.Title); + Assert.AreEqual(exception, problemDetailsContext.Exception); + Assert.AreEqual(exception.Message, problemDetailsContext.ProblemDetails.Detail); + } + + [TestMethod] + public async Task HandleException_WhenVerificationException_ShouldReturnProblemDetails() + { + var httpContext = new DefaultHttpContext(); + var exception = new VerificationException("Verification error"); + + ProblemDetailsContext? problemDetailsContext = null; + _mockProblemDetailsService.Setup(x => + x.TryWriteAsync(It.IsAny())) + .Callback(context => problemDetailsContext = context) + .ReturnsAsync(true); + + await _handler.TryHandleAsync(httpContext, exception, CancellationToken.None); + + Assert.AreEqual((int)HttpStatusCode.BadRequest, httpContext.Response.StatusCode); + Assert.IsNotNull(problemDetailsContext); + Assert.AreEqual("https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.1", + problemDetailsContext.ProblemDetails.Type); + Assert.AreEqual("A verification error occurred", + problemDetailsContext.ProblemDetails.Title); + Assert.AreEqual(exception, problemDetailsContext.Exception); + Assert.AreEqual(exception.Message, problemDetailsContext.ProblemDetails.Detail); + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Exceptions/ValidationExceptionHandlerTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Exceptions/ValidationExceptionHandlerTests.cs new file mode 100644 index 00000000..a2b50a72 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Exceptions/ValidationExceptionHandlerTests.cs @@ -0,0 +1,54 @@ +using System.Net; +using FluentValidation; +using FluentValidation.Results; +using Microsoft.AspNetCore.Http; +using Moq; +using ReasnAPI.Exceptions; + +namespace ReasnAPI.Tests.UnitTests.Exceptions; + +[TestClass] +public class ValidationExceptionHandlerTests +{ + private Mock _mockProblemDetailsService = null!; + private ValidationExceptionHandler _handler = null!; + + [TestInitialize] + public void Setup() + { + _mockProblemDetailsService = new Mock(); + _handler = new ValidationExceptionHandler(_mockProblemDetailsService.Object); + } + + [TestMethod] + public async Task HandleException_WhenValidationException_ShouldReturnProblemDetails() + { + var httpContext = new DefaultHttpContext(); + var exception = new ValidationException(new List + { + new ("Email", "'Email' must not be empty."), + new ("Password", "'Password' must not be empty.") + }); + + ProblemDetailsContext? problemDetailsContext = null; + _mockProblemDetailsService.Setup(x => + x.TryWriteAsync(It.IsAny())) + .Callback(context => problemDetailsContext = context) + .ReturnsAsync(true); + + await _handler.TryHandleAsync(httpContext, exception, CancellationToken.None); + + Assert.AreEqual((int)HttpStatusCode.BadRequest, httpContext.Response.StatusCode); + Assert.IsNotNull(problemDetailsContext); + Assert.AreEqual("https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.1", + problemDetailsContext.ProblemDetails.Type); + Assert.AreEqual("A validation error occurred", + problemDetailsContext.ProblemDetails.Title); + Assert.AreEqual(exception, problemDetailsContext.Exception); + Assert.AreEqual("One or more validation errors occurred", + problemDetailsContext.ProblemDetails.Detail); + + Assert.IsNotNull(problemDetailsContext.ProblemDetails.Extensions); + Assert.IsTrue(problemDetailsContext.ProblemDetails.Extensions.ContainsKey("errors")); + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Services/Authentication/AuthServiceTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Services/Authentication/AuthServiceTests.cs new file mode 100644 index 00000000..78c1a0a1 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Services/Authentication/AuthServiceTests.cs @@ -0,0 +1,125 @@ +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.WebUtilities; +using Moq; +using Moq.EntityFrameworkCore; +using ReasnAPI.Models.Authentication; +using ReasnAPI.Models.Database; +using ReasnAPI.Models.DTOs; +using ReasnAPI.Services.Authentication; +using ReasnAPI.Services.Exceptions; + +namespace ReasnAPI.Tests.UnitTests.Services.Authentication; + +[TestClass] +public class AuthServiceTests +{ + private Mock _mockContext = null!; + private PasswordHasher _hasher = null!; + private AuthService _service = null!; + + [TestInitialize] + public void Setup() + { + _mockContext = new Mock(); + _hasher = new PasswordHasher(); + _service = new AuthService(_mockContext.Object); + + var user = new User + { + Email = "jon.snow@castleblack.com", + Username = "jsnow", + Password = _hasher.HashPassword(null!, "password") + }; + + _mockContext.Setup(c => c.Users) + .ReturnsDbSet(new List { user }); + } + + [TestMethod] + public void Login_WhenUserExistsAndPasswordIsCorrect_ShouldReturnUser() + { + var request = new LoginRequest + { + Email = "jon.snow@castleblack.com", + Password = "password" + }; + + var result = _service.Login(request); + + Assert.IsNotNull(result); + Assert.IsInstanceOfType(result, typeof(User)); + } + + [TestMethod] + public void Login_WhenUserDoesNotExist_ShouldThrowNotFoundException() + { + var request = new LoginRequest + { + Email = "jon.notsnow@castleblack.com" + }; + + Assert.ThrowsException(() => _service.Login(request)); + } + + [TestMethod] + public void Login_WhenPasswordIsIncorrect_ShouldThrowVerificationException() + { + var request = new LoginRequest + { + Email = "jon.snow@castleblack.com", + Password = "wrong-password" + }; + + Assert.ThrowsException(() => _service.Login(request)); + } + + [TestMethod] + public void Register_WhenUserWithEmailAlreadyExists_ShouldThrowBadRequestException() + { + var request = new RegisterRequest + { + Email = "jon.snow@castleblack.com" + }; + + Assert.ThrowsException(() => _service.Register(request)); + } + + [TestMethod] + public void Register_WhenUserWithUsernameAlreadyExists_ShouldThrowBadRequestException() + { + var request = new RegisterRequest + { + Email = "jon.stark@castleblack.com", + Username = "jsnow" + }; + + Assert.ThrowsException(() => _service.Register(request)); + } + + [TestMethod] + public void Register_WhenUserDoesNotExist_ShouldReturnRegisteredUser() + { + var request = new RegisterRequest + { + Name = "Jon", + Surname = "Stark", + Email = "jon.stark@castleblack.com", + Username = "jstark", + Password = "S3cureP@ssword!", + Phone = "+123 456789", + Address = new AddressDto + { + Street = "The Wall", + City = "Castle Black", + Country = "Westeros", + State = "The North" + }, + Role = "User" + }; + + var result = _service.Register(request); + + Assert.IsNotNull(result); + Assert.IsInstanceOfType(result, typeof(User)); + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Services/Authentication/TokenServiceTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Services/Authentication/TokenServiceTests.cs new file mode 100644 index 00000000..b2c5a995 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Services/Authentication/TokenServiceTests.cs @@ -0,0 +1,82 @@ +using System.IdentityModel.Tokens.Jwt; +using System.Security.Cryptography; +using Microsoft.Extensions.Configuration; +using Moq; +using ReasnAPI.Models.Database; +using ReasnAPI.Models.Enums; +using ReasnAPI.Services.Authentication; + +namespace ReasnAPI.Tests.UnitTests.Services.Authentication; + +[TestClass] +public class TokenServiceTests +{ + private const int DurationInHours = 8; + private const string IssAudValue = "http://localhost:5272"; + private TokenService _service = null!; + private Mock _mockConfiguration = null!; + private User _validUser = null!; + + [TestInitialize] + public void Setup() + { + _mockConfiguration = new Mock(); + + var bytes = new byte[32]; + RandomNumberGenerator.Fill(bytes); + _mockConfiguration.Setup(x => + x["JwtSettings:Key"]).Returns(Convert.ToBase64String(bytes)); + + _mockConfiguration.Setup(x => + x["JwtSettings:Issuer"]).Returns(IssAudValue); + + var mockSection = new Mock(); + var mockAudienceValue = new Mock(); + mockAudienceValue.Setup(x => x.Value).Returns(IssAudValue); + mockSection.Setup(x => + x.GetChildren()).Returns(new List { mockAudienceValue.Object }); + _mockConfiguration.Setup(x => + x.GetSection("JwtSettings:Audiences")).Returns(mockSection.Object); + + var mockDurationValue = new Mock(); + mockDurationValue.SetupGet(x => x.Value).Returns(DurationInHours.ToString()); + _mockConfiguration.Setup(x => + x.GetSection("JwtSettings:DurationInHours")).Returns(mockDurationValue.Object); + + _service = new TokenService(_mockConfiguration.Object); + + _validUser = new User { + Id = 1, + Name = "Jon", + Surname = "Snow", + Email = "jon.snow@castleblack.com", + Role = UserRole.User + }; + } + + [TestMethod] + public void GenerateToken_WhenValidUser_ShouldReturnTokenPayload() + { + var result = _service.GenerateToken(_validUser); + + Assert.IsNotNull(result); + Assert.AreEqual("Bearer", result.TokenType); + Assert.IsNotNull(result.AccessToken); + Assert.AreEqual(DurationInHours * 60 * 60, result.ExpiresIn); + } + + [TestMethod] + public void GenerateToken_WhenValidUser_ShouldReturnValidToken() + { + var result = _service.GenerateToken(_validUser); + + var tokenHandler = new JwtSecurityTokenHandler(); + var token = tokenHandler.ReadToken(result.AccessToken) as JwtSecurityToken; + + Assert.IsNotNull(token); + Assert.AreEqual(IssAudValue, token.Issuer); + Assert.AreEqual(IssAudValue, token.Audiences.First()); + Assert.AreEqual(_validUser.Email, token.Subject); + Assert.AreEqual(DurationInHours * 60 * 60, (token.ValidTo - token.ValidFrom).TotalSeconds); + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/AddressValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/AddressValidatorTests.cs new file mode 100644 index 00000000..f4a89585 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/AddressValidatorTests.cs @@ -0,0 +1,205 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.UnitTests.Validators; + +[TestClass] +public class AddressValidatorTests +{ + private AddressValidator _validator = null!; + + [TestInitialize] + public void Setup() + { + _validator = new AddressValidator(); + } + + [TestMethod] + public void Validate_WhenValidRequest_ShouldReturnTrue() + { + var request = new AddressDto + { + Street = "The Wall", + City = "Castle Black", + Country = "Westeros", + State = "The North", + ZipCode = "12345" + }; + var result = _validator.Validate(request); + + Assert.IsTrue(result.IsValid); + } + + [TestMethod] + public void Validate_WhenEmptyStreet_ShouldReturnFalse() + { + var request = new AddressDto { Street = "" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Street' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenStreetTooLong_ShouldReturnFalse() + { + var request = new AddressDto { Street = new string('a', 65) }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == + "The length of 'Street' must be 64 characters or fewer. You entered 65 characters." + )); + } + + [TestMethod] + public void Validate_WhenInvalidStreet_ShouldReturnFalse() + { + var request = new AddressDto { Street = "The Wall!" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Street' is not in the correct format." + )); + } + + [TestMethod] + public void Validate_WhenEmptyCity_ShouldReturnFalse() + { + var request = new AddressDto { City = "" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'City' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenCityTooLong_ShouldReturnFalse() + { + var request = new AddressDto { City = new string('a', 65) }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == + "The length of 'City' must be 64 characters or fewer. You entered 65 characters." + )); + } + + [TestMethod] + public void Validate_WhenInvalidCity_ShouldReturnFalse() + { + var request = new AddressDto { City = "Castle Black!" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'City' is not in the correct format." + )); + } + + [TestMethod] + public void Validate_WhenEmptyCountry_ShouldReturnFalse() + { + var request = new AddressDto { Country = "" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Country' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenCountryTooLong_ShouldReturnFalse() + { + var request = new AddressDto { Country = new string('a', 65) }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "" + + "The length of 'Country' must be 64 characters or fewer. You entered 65 characters." + )); + } + + [TestMethod] + public void Validate_WhenInvalidCountry_ShouldReturnFalse() + { + var request = new AddressDto { Country = "Westeros!" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Country' is not in the correct format." + )); + } + + [TestMethod] + public void Validate_WhenEmptyState_ShouldReturnFalse() + { + var request = new AddressDto { State = "" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'State' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenStateTooLong_ShouldReturnFalse() + { + var request = new AddressDto { State = new string('a', 65) }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "" + + "The length of 'State' must be 64 characters or fewer. You entered 65 characters." + )); + } + + [TestMethod] + public void Validate_WhenInvalidState_ShouldReturnFalse() + { + var request = new AddressDto { State = "The North!" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'State' is not in the correct format." + )); + } + + [TestMethod] + public void Validate_WhenZipCodeTooLong_ShouldReturnFalse() + { + var request = new AddressDto { ZipCode = new string('a', 9) }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == + "The length of 'Zip Code' must be 8 characters or fewer. You entered 9 characters." + )); + } + + [TestMethod] + public void Validate_WhenInvalidZipCode_ShouldReturnFalse() + { + var request = new AddressDto { ZipCode = "12345!" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Zip Code' is not in the correct format." + )); + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/Authentication/LoginRequestValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/Authentication/LoginRequestValidatorTests.cs new file mode 100644 index 00000000..d1c2b67a --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/Authentication/LoginRequestValidatorTests.cs @@ -0,0 +1,62 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using ReasnAPI.Models.Authentication; +using ReasnAPI.Validators.Authentication; + +namespace ReasnAPI.Tests.UnitTests.Validators.Authentication; + +[TestClass] +public class LoginRequestValidatorTests +{ + private LoginRequestValidator _validator = null!; + + [TestInitialize] + public void Setup() + { + _validator = new LoginRequestValidator(); + } + + [TestMethod] + public void Validate_WhenValidRequest_ShouldReturnTrue() + { + var request = new LoginRequest { Email = "test@example.com", Password = "password" }; + var result = _validator.Validate(request); + + Assert.IsTrue(result.IsValid); + } + + [TestMethod] + public void Validate_WhenEmptyEmail_ShouldReturnFalse() + { + var request = new LoginRequest { Email = "", Password = "password" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Email' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenInvalidEmail_ShouldReturnFalse() + { + var request = new LoginRequest { Email = "invalid email", Password = "password" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Email' is not a valid email address." + )); + } + + [TestMethod] + public void Validate_WhenEmptyPassword_ShouldReturnFalse() + { + var request = new LoginRequest { Email = "test@example.com", Password = "" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Password' must not be empty." + )); + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/Authentication/RegisterRequestValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/Authentication/RegisterRequestValidatorTests.cs new file mode 100644 index 00000000..7ab00d5e --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/Authentication/RegisterRequestValidatorTests.cs @@ -0,0 +1,278 @@ +using ReasnAPI.Validators.Authentication; +using ReasnAPI.Models.Authentication; +using ReasnAPI.Models.DTOs; + +namespace ReasnAPI.Tests.UnitTests.Validators.Authentication; + +[TestClass] +public class RegisterRequestValidatorTests +{ + private RegisterRequestValidator _validator = null!; + + [TestInitialize] + public void Setup() + { + _validator = new RegisterRequestValidator(); + } + + [TestMethod] + public void Validate_WhenValidRequest_ShouldReturnTrue() + { + var request = new RegisterRequest + { + Name = "Jon", + Surname = "Snow", + Email = "jon.snow@castleblack.com", + Username = "jonSnow", + Password = "S3cureP@ssword!", + Phone = "+123 456789", + Address = new AddressDto + { + Street = "The Wall", + City = "Castle Black", + Country = "Westeros", + State = "The North" + }, + Role = "User" + }; + var result = _validator.Validate(request); + + Assert.IsTrue(result.IsValid); + } + + [TestMethod] + public void Validate_WhenEmptyName_ShouldReturnFalse() + { + var request = new RegisterRequest { Name = "" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Name' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenNameTooLong_ShouldReturnFalse() + { + var request = new RegisterRequest { Name = new string('a', 65) }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Console.WriteLine(result.Errors[0]); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == + "The length of 'Name' must be 64 characters or fewer. You entered 65 characters." + )); + } + + [TestMethod] + public void Validate_WhenInvalidName_ShouldReturnFalse() + { + var request = new RegisterRequest { Name = "123" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Console.WriteLine(result.Errors[0]); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Name' is not in the correct format." + )); + } + + [TestMethod] + public void Validate_WhenEmptySurname_ShouldReturnFalse() + { + var request = new RegisterRequest { Surname = "" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Surname' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenSurnameTooLong_ShouldReturnFalse() + { + var request = new RegisterRequest { Surname = new string('a', 65) }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == + "The length of 'Surname' must be 64 characters or fewer. You entered 65 characters." + )); + } + + [TestMethod] + public void Validate_WhenInvalidSurname_ShouldReturnFalse() + { + var request = new RegisterRequest { Surname = "123" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Surname' is not in the correct format." + )); + } + + [TestMethod] + public void Validate_WhenEmptyUsername_ShouldReturnFalse() + { + var request = new RegisterRequest { Username = "" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Username' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenUsernameTooLong_ShouldReturnFalse() + { + var request = new RegisterRequest { Username = new string('a', 65) }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == + "The length of 'Username' must be 64 characters or fewer. You entered 65 characters." + )); + } + + [TestMethod] + public void Validate_WhenInvalidUsername_ShouldReturnFalse() + { + var request = new RegisterRequest { Username = "user name" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Username' is not in the correct format." + )); + } + + [TestMethod] + public void Validate_WhenEmptyEmail_ShouldReturnFalse() + { + var request = new RegisterRequest { Email = "" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Email' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenEmailTooLong_ShouldReturnFalse() + { + var request = new RegisterRequest { Email = new string('a', 256) }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == + "The length of 'Email' must be 255 characters or fewer. You entered 256 characters." + )); + } + + [TestMethod] + public void Validate_WhenInvalidEmail_ShouldReturnFalse() + { + var request = new RegisterRequest { Email = "invalid email" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Email' is not a valid email address." + )); + } + + [TestMethod] + public void Validate_WhenEmptyPassword_ShouldReturnFalse() + { + var request = new RegisterRequest { Password = "" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Password' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenInvalidPassword_ShouldReturnFalse() + { + var request = new RegisterRequest { Password = "password" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == + "Password must contain at least one uppercase letter, " + + "one lowercase letter, one number, and be at least 6 characters long." + )); + } + + [TestMethod] + public void Validate_WhenEmptyPhone_ShouldReturnTrue() + { + var request = new RegisterRequest { Phone = "" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.Errors.Exists( + e => e.ErrorMessage == "'Phone' is not in the correct format." + )); + } + + [TestMethod] + public void Validate_WhenInvalidPhone_ShouldReturnFalse() + { + var request = new RegisterRequest { Phone = "invalid phone" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Console.WriteLine(result.Errors[5]); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Phone' is not in the correct format." + )); + } + + [TestMethod] + public void Validate_WhenEmptyAddress_ShouldReturnFalse() + { + var request = new RegisterRequest { Address = null }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Address' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenEmptyRole_ShouldReturnFalse() + { + var request = new RegisterRequest { Role = "" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Role' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenInvalidRole_ShouldReturnFalse() + { + var request = new RegisterRequest { Role = "invalid role" }; + var result = _validator.Validate(request); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "Role must be either 'User' or 'Organizer'." + )); + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Models/Authentication/RegisterRequest.cs b/Server/ReasnAPI/ReasnAPI/Models/Authentication/RegisterRequest.cs index 59dae251..cbcbb81a 100644 --- a/Server/ReasnAPI/ReasnAPI/Models/Authentication/RegisterRequest.cs +++ b/Server/ReasnAPI/ReasnAPI/Models/Authentication/RegisterRequest.cs @@ -1,5 +1,4 @@ using ReasnAPI.Models.DTOs; -using ReasnAPI.Models.Enums; namespace ReasnAPI.Models.Authentication; @@ -10,9 +9,7 @@ public class RegisterRequest public string Email { get; set; } = null!; public string Username { get; set; } = null!; public string Password { get; set; } = null!; - public string? Phone { get; set; } - public AddressDto Address { get; set; } = null!; public string Role { get; set; } = null!; } \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Services/Authentication/AuthService.cs b/Server/ReasnAPI/ReasnAPI/Services/Authentication/AuthService.cs index 5231ce8d..529685f9 100644 --- a/Server/ReasnAPI/ReasnAPI/Services/Authentication/AuthService.cs +++ b/Server/ReasnAPI/ReasnAPI/Services/Authentication/AuthService.cs @@ -21,7 +21,7 @@ public AuthService(ReasnContext context) public User Login(LoginRequest request) { var user = _context.Users.FirstOrDefault(u => - EF.Functions.ILike(u.Email, request.Email)); + u.Email.ToUpper() == request.Email.ToUpper()); if (user is null) { @@ -42,8 +42,8 @@ public User Login(LoginRequest request) public User Register(RegisterRequest request) { var userAlreadyExists = _context.Users.Any(u => - EF.Functions.ILike(u.Email, request.Email) || - EF.Functions.ILike(u.Username, request.Username)); + u.Email.ToUpper() == request.Email.ToUpper() || + u.Username.ToUpper() == request.Username.ToUpper()); if (userAlreadyExists) { diff --git a/Server/ReasnAPI/ReasnAPI/Validators/Authentication/LoginRequestValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/Authentication/LoginRequestValidator.cs index 3b85c79d..09a625d6 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/Authentication/LoginRequestValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/Authentication/LoginRequestValidator.cs @@ -9,8 +9,7 @@ public LoginRequestValidator() { RuleFor(r => r.Email) .NotEmpty() - .EmailAddress() - .WithMessage("Email is not in expected format"); + .EmailAddress(); RuleFor(r => r.Password) .NotEmpty(); diff --git a/Server/ReasnAPI/ReasnAPI/Validators/Authentication/RegisterRequestValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/Authentication/RegisterRequestValidator.cs index 7b82e0cc..585b8007 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/Authentication/RegisterRequestValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/Authentication/RegisterRequestValidator.cs @@ -22,32 +22,30 @@ public RegisterRequestValidator() .NotEmpty() .MaximumLength(64) .Matches(@"^[\p{L}\d._%+-]+$"); - + RuleFor(r => r.Email) .NotEmpty() .MaximumLength(255) - .EmailAddress() - .WithMessage("Email is not in expected format"); + .EmailAddress(); RuleFor(r => r.Password) .NotEmpty() .Matches(@"^((?=\S*?[A-Z])(?=\S*?[a-z])(?=\S*?[0-9]).{6,})\S$") .WithMessage( "Password must contain at least one uppercase letter, " + - "one lowercase letter, one number, and be at least 6 characters long"); - + "one lowercase letter, one number, and be at least 6 characters long."); + RuleFor(r => r.Phone) .Matches(@"^\+\d{1,3}\s\d{1,15}$") - .When(r => !string.IsNullOrEmpty(r.Phone)) - .WithMessage("Phone number is not in expected format"); + .When(r => !string.IsNullOrEmpty(r.Phone)); RuleFor(r => r.Address) .NotNull() - .SetValidator(new AddressValidator()); + .SetValidator(new AddressValidator()!); RuleFor(r => r.Role) .NotEmpty() .Must(r => r == UserRole.User.ToString() || r == UserRole.Organizer.ToString()) - .WithMessage($"Role must be either '{UserRole.User.ToString()}' or '{UserRole.Organizer.ToString()}'"); + .WithMessage($"Role must be either '{UserRole.User.ToString()}' or '{UserRole.Organizer.ToString()}'."); } } \ No newline at end of file From 26348f0bc6e8342dd0c9c2d38fa80f01d21c142a Mon Sep 17 00:00:00 2001 From: raczu Date: Tue, 4 Jun 2024 17:14:35 +0200 Subject: [PATCH 22/24] style: format code with dotnet format --- Server/ReasnAPI/ReasnAPI/Common/IAssemblyMarker.cs | 2 +- .../ReasnAPI/Controllers/AuthController.cs | 6 +++--- .../ReasnAPI/Exceptions/ServiceExceptionHandler.cs | 14 +++++++------- .../Exceptions/ValidationExceptionHandler.cs | 4 ++-- Server/ReasnAPI/ReasnAPI/Mappers/AddressMapper.cs | 2 +- Server/ReasnAPI/ReasnAPI/Mappers/InterestMapper.cs | 2 +- .../ReasnAPI/Mappers/UserInterestMapper.cs | 2 +- Server/ReasnAPI/ReasnAPI/Models/DTOs/UserDto.cs | 6 ++++-- .../ReasnAPI/ReasnAPI/Models/Enums/EventStatus.cs | 6 +++--- Server/ReasnAPI/ReasnAPI/Models/Enums/UserRole.cs | 8 ++++---- .../Services/Authentication/AuthService.cs | 14 +++++++------- .../Services/Authentication/TokenService.cs | 12 ++++++------ .../Services/Exceptions/BadRequestException.cs | 4 ++-- .../Services/Exceptions/NotFoundException.cs | 2 +- .../Services/Exceptions/VerificationException.cs | 4 ++-- 15 files changed, 45 insertions(+), 43 deletions(-) diff --git a/Server/ReasnAPI/ReasnAPI/Common/IAssemblyMarker.cs b/Server/ReasnAPI/ReasnAPI/Common/IAssemblyMarker.cs index 1031a093..916dc1d9 100644 --- a/Server/ReasnAPI/ReasnAPI/Common/IAssemblyMarker.cs +++ b/Server/ReasnAPI/ReasnAPI/Common/IAssemblyMarker.cs @@ -2,5 +2,5 @@ namespace ReasnAPI.Validators; public interface IAssemblyMarker { - + } \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Controllers/AuthController.cs b/Server/ReasnAPI/ReasnAPI/Controllers/AuthController.cs index 9342a620..9a73f067 100644 --- a/Server/ReasnAPI/ReasnAPI/Controllers/AuthController.cs +++ b/Server/ReasnAPI/ReasnAPI/Controllers/AuthController.cs @@ -26,11 +26,11 @@ public IActionResult Login( { validator.ValidateAndThrow(request); var user = _authService.Login(request); - + var tokenPayload = _tokenService.GenerateToken(user); return Ok(tokenPayload); } - + [HttpPost("register")] public IActionResult Register( [FromBody] RegisterRequest request, @@ -43,7 +43,7 @@ public IActionResult Register( action: nameof(UsersController.GetUserByUsername), controller: "Users", values: new { username = user.Username }); - + return Created(location, user.ToDto()); } } \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Exceptions/ServiceExceptionHandler.cs b/Server/ReasnAPI/ReasnAPI/Exceptions/ServiceExceptionHandler.cs index 5a710393..fd76c213 100644 --- a/Server/ReasnAPI/ReasnAPI/Exceptions/ServiceExceptionHandler.cs +++ b/Server/ReasnAPI/ReasnAPI/Exceptions/ServiceExceptionHandler.cs @@ -8,12 +8,12 @@ namespace ReasnAPI.Exceptions; public class ServiceExceptionHandler : IExceptionHandler { private readonly IProblemDetailsService _problemDetailsService; - + public ServiceExceptionHandler(IProblemDetailsService problemDetailsService) { _problemDetailsService = problemDetailsService; } - + public async ValueTask TryHandleAsync( HttpContext httpContext, Exception exception, @@ -23,7 +23,7 @@ public async ValueTask TryHandleAsync( { Detail = exception.Message }; - + switch (exception) { case BadRequestException: @@ -31,23 +31,23 @@ public async ValueTask TryHandleAsync( problemDetails.Type = "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.1"; problemDetails.Title = "A bad request was made"; break; - + case NotFoundException: httpContext.Response.StatusCode = (int)HttpStatusCode.NotFound; problemDetails.Type = "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.4"; problemDetails.Title = "A resource was not found"; break; - + case VerificationException: httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; problemDetails.Type = "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.1"; problemDetails.Title = "A verification error occurred"; break; - + default: return false; } - + return await _problemDetailsService.TryWriteAsync(new ProblemDetailsContext { HttpContext = httpContext, diff --git a/Server/ReasnAPI/ReasnAPI/Exceptions/ValidationExceptionHandler.cs b/Server/ReasnAPI/ReasnAPI/Exceptions/ValidationExceptionHandler.cs index 296415d1..8cbc68c9 100644 --- a/Server/ReasnAPI/ReasnAPI/Exceptions/ValidationExceptionHandler.cs +++ b/Server/ReasnAPI/ReasnAPI/Exceptions/ValidationExceptionHandler.cs @@ -7,12 +7,12 @@ namespace ReasnAPI.Exceptions; public class ValidationExceptionHandler : IExceptionHandler { private readonly IProblemDetailsService _problemDetailsService; - + public ValidationExceptionHandler(IProblemDetailsService problemDetailsService) { _problemDetailsService = problemDetailsService; } - + public async ValueTask TryHandleAsync( HttpContext httpContext, Exception exception, diff --git a/Server/ReasnAPI/ReasnAPI/Mappers/AddressMapper.cs b/Server/ReasnAPI/ReasnAPI/Mappers/AddressMapper.cs index e4ef17a1..f07e575d 100644 --- a/Server/ReasnAPI/ReasnAPI/Mappers/AddressMapper.cs +++ b/Server/ReasnAPI/ReasnAPI/Mappers/AddressMapper.cs @@ -15,7 +15,7 @@ public static AddressDto ToDto(this Address address) ZipCode = address.ZipCode }; } - + public static List ToDtoList(this IEnumerable
addresses) { return addresses.Select(ToDto).ToList(); diff --git a/Server/ReasnAPI/ReasnAPI/Mappers/InterestMapper.cs b/Server/ReasnAPI/ReasnAPI/Mappers/InterestMapper.cs index 1ea23dd2..c8e2fe3f 100644 --- a/Server/ReasnAPI/ReasnAPI/Mappers/InterestMapper.cs +++ b/Server/ReasnAPI/ReasnAPI/Mappers/InterestMapper.cs @@ -12,7 +12,7 @@ public static InterestDto ToDto(this Interest interest) Name = interest.Name }; } - + public static List ToDtoList(this IEnumerable interests) { return interests.Select(ToDto).ToList(); diff --git a/Server/ReasnAPI/ReasnAPI/Mappers/UserInterestMapper.cs b/Server/ReasnAPI/ReasnAPI/Mappers/UserInterestMapper.cs index a4f1f831..ae9bdf0a 100644 --- a/Server/ReasnAPI/ReasnAPI/Mappers/UserInterestMapper.cs +++ b/Server/ReasnAPI/ReasnAPI/Mappers/UserInterestMapper.cs @@ -13,7 +13,7 @@ public static UserInterestDto ToDto(this UserInterest userInterest) Level = userInterest.Level }; } - + public static List ToDtoList(this IEnumerable userInterests) { return userInterests.Select(ToDto).ToList(); diff --git a/Server/ReasnAPI/ReasnAPI/Models/DTOs/UserDto.cs b/Server/ReasnAPI/ReasnAPI/Models/DTOs/UserDto.cs index f06d2717..3d16dc47 100644 --- a/Server/ReasnAPI/ReasnAPI/Models/DTOs/UserDto.cs +++ b/Server/ReasnAPI/ReasnAPI/Models/DTOs/UserDto.cs @@ -1,7 +1,9 @@ using ReasnAPI.Models.Enums; -namespace ReasnAPI.Models.DTOs { - public class UserDto { +namespace ReasnAPI.Models.DTOs +{ + public class UserDto + { public string Username { get; set; } = null!; public string Name { get; set; } = null!; public string Surname { get; set; } = null!; diff --git a/Server/ReasnAPI/ReasnAPI/Models/Enums/EventStatus.cs b/Server/ReasnAPI/ReasnAPI/Models/Enums/EventStatus.cs index beeb82e1..102991eb 100644 --- a/Server/ReasnAPI/ReasnAPI/Models/Enums/EventStatus.cs +++ b/Server/ReasnAPI/ReasnAPI/Models/Enums/EventStatus.cs @@ -2,8 +2,8 @@ public enum EventStatus { - Completed, - Inprogress, - Approved, + Completed, + Inprogress, + Approved, WaitingForApproval } \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Models/Enums/UserRole.cs b/Server/ReasnAPI/ReasnAPI/Models/Enums/UserRole.cs index fb13bf68..9b22fe02 100644 --- a/Server/ReasnAPI/ReasnAPI/Models/Enums/UserRole.cs +++ b/Server/ReasnAPI/ReasnAPI/Models/Enums/UserRole.cs @@ -5,11 +5,11 @@ namespace ReasnAPI.Models.Enums; public enum UserRole { [PgName("User")] - User, - + User, + [PgName("Organizer")] - Organizer, - + Organizer, + [PgName("Admin")] Admin } \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Services/Authentication/AuthService.cs b/Server/ReasnAPI/ReasnAPI/Services/Authentication/AuthService.cs index 529685f9..1d66a426 100644 --- a/Server/ReasnAPI/ReasnAPI/Services/Authentication/AuthService.cs +++ b/Server/ReasnAPI/ReasnAPI/Services/Authentication/AuthService.cs @@ -20,14 +20,14 @@ public AuthService(ReasnContext context) public User Login(LoginRequest request) { - var user = _context.Users.FirstOrDefault(u => + var user = _context.Users.FirstOrDefault(u => u.Email.ToUpper() == request.Email.ToUpper()); if (user is null) { throw new NotFoundException("Not found user related with provided email"); } - + var result = _hasher.VerifyHashedPassword( user, user.Password, request.Password); @@ -35,10 +35,10 @@ public User Login(LoginRequest request) { throw new VerificationException("Provided password is incorrect"); } - + return user; } - + public User Register(RegisterRequest request) { var userAlreadyExists = _context.Users.Any(u => @@ -50,7 +50,7 @@ public User Register(RegisterRequest request) throw new BadRequestException( "User with provided email or username already exists"); } - + var user = new User { Name = request.Name, @@ -70,10 +70,10 @@ public User Register(RegisterRequest request) } }; _context.Users.Add(user); - + user.Password = _hasher.HashPassword(user, request.Password); _context.SaveChanges(); - + return user; } } \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Services/Authentication/TokenService.cs b/Server/ReasnAPI/ReasnAPI/Services/Authentication/TokenService.cs index 87d4e519..e6752045 100644 --- a/Server/ReasnAPI/ReasnAPI/Services/Authentication/TokenService.cs +++ b/Server/ReasnAPI/ReasnAPI/Services/Authentication/TokenService.cs @@ -10,24 +10,24 @@ namespace ReasnAPI.Services.Authentication; public class TokenService { private readonly IConfiguration _configuration; - - public TokenService(IConfiguration configuration) => + + public TokenService(IConfiguration configuration) => _configuration = configuration; - + public TokenPayload GenerateToken(User user) { var tokenHandler = new JwtSecurityTokenHandler(); var tokenLifetime = TimeSpan.FromHours( _configuration.GetValue("JwtSettings:DurationInHours")); - + var key = Encoding.UTF8.GetBytes(_configuration["JwtSettings:Key"]!); var issuer = _configuration["JwtSettings:Issuer"]!; var audiences = _configuration.GetSection("JwtSettings:Audiences") .Get>()!; - + var tokenDescriptor = new SecurityTokenDescriptor { - Subject = new ClaimsIdentity(new [] + Subject = new ClaimsIdentity(new[] { new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), new Claim(JwtRegisteredClaimNames.Sub, user.Email), diff --git a/Server/ReasnAPI/ReasnAPI/Services/Exceptions/BadRequestException.cs b/Server/ReasnAPI/ReasnAPI/Services/Exceptions/BadRequestException.cs index 2e8af887..7b630bda 100644 --- a/Server/ReasnAPI/ReasnAPI/Services/Exceptions/BadRequestException.cs +++ b/Server/ReasnAPI/ReasnAPI/Services/Exceptions/BadRequestException.cs @@ -5,6 +5,6 @@ public class BadRequestException : Exception public BadRequestException() { } public BadRequestException(string message) : base(message) { } - - public BadRequestException(string message, Exception inner) : base(message, inner) { } + + public BadRequestException(string message, Exception inner) : base(message, inner) { } } \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Services/Exceptions/NotFoundException.cs b/Server/ReasnAPI/ReasnAPI/Services/Exceptions/NotFoundException.cs index 90ecb02a..781b52b9 100644 --- a/Server/ReasnAPI/ReasnAPI/Services/Exceptions/NotFoundException.cs +++ b/Server/ReasnAPI/ReasnAPI/Services/Exceptions/NotFoundException.cs @@ -5,6 +5,6 @@ public class NotFoundException : Exception public NotFoundException() { } public NotFoundException(string message) : base(message) { } - + public NotFoundException(string message, Exception inner) : base(message, inner) { } } \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Services/Exceptions/VerificationException.cs b/Server/ReasnAPI/ReasnAPI/Services/Exceptions/VerificationException.cs index 97525c39..cd5a1749 100644 --- a/Server/ReasnAPI/ReasnAPI/Services/Exceptions/VerificationException.cs +++ b/Server/ReasnAPI/ReasnAPI/Services/Exceptions/VerificationException.cs @@ -5,6 +5,6 @@ public class VerificationException : Exception public VerificationException() { } public VerificationException(string message) : base(message) { } - - public VerificationException(string message, Exception inner) : base(message, inner) { } + + public VerificationException(string message, Exception inner) : base(message, inner) { } } \ No newline at end of file From fe7e7bee357bb65aaab10d8a986ea51d79a06d2d Mon Sep 17 00:00:00 2001 From: raczu Date: Wed, 5 Jun 2024 02:23:33 +0200 Subject: [PATCH 23/24] refactor: rewrite validators to use fluent validation --- .../ServiceExceptionHandlerTests.cs | 24 +- .../ValidationExceptionHandlerTests.cs | 10 +- .../Authentication/AuthServiceTests.cs | 20 +- .../Authentication/TokenServiceTests.cs | 25 +- .../Validators/AddressValidatorTests.cs | 128 ++++-- .../LoginRequestValidatorTests.cs | 25 +- .../RegisterRequestValidatorTests.cs | 163 +++++--- .../Validators/CommentValidatorTests.cs | 63 +++ .../Validators/EventValidatorTests.cs | 208 ++++++++++ .../Validators/InterestValidatorTests.cs | 78 ++++ .../Validators/ParameterValidatorTests.cs | 128 ++++++ .../UnitTests/Validators/TagValidatorTests.cs | 78 ++++ .../Validators/UserValidatorTests.cs | 247 ++++++++++++ .../Validators/CommentValidatorTests.cs | 65 --- .../Validators/EventValidatorTests.cs | 271 ------------- .../Validators/InterestValidatorTests.cs | 62 --- .../Validators/ParameterValidatorTests.cs | 109 ----- .../Validators/TagValidatorTests.cs | 62 --- .../Validators/UserValidatorTests.cs | 375 ------------------ .../ReasnAPI/Validators/AddressValidator.cs | 14 +- .../Authentication/LoginRequestValidator.cs | 4 +- .../RegisterRequestValidator.cs | 6 +- .../ReasnAPI/Validators/CommentValidator.cs | 32 +- .../ReasnAPI/Validators/EventValidator.cs | 90 ++--- .../ReasnAPI/Validators/IValidator.cs | 9 - .../ReasnAPI/Validators/InterestValidator.cs | 33 +- .../ReasnAPI/Validators/ParameterValidator.cs | 53 +-- .../ReasnAPI/Validators/TagValidator.cs | 33 +- .../ReasnAPI/Validators/UserValidator.cs | 118 ++---- 29 files changed, 1176 insertions(+), 1357 deletions(-) create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/CommentValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/EventValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/InterestValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/ParameterValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/TagValidatorTests.cs create mode 100644 Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/UserValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs delete mode 100644 Server/ReasnAPI/ReasnAPI/Validators/IValidator.cs diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Exceptions/ServiceExceptionHandlerTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Exceptions/ServiceExceptionHandlerTests.cs index c2f31712..15a71958 100644 --- a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Exceptions/ServiceExceptionHandlerTests.cs +++ b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Exceptions/ServiceExceptionHandlerTests.cs @@ -11,14 +11,14 @@ public class ServiceExceptionHandlerTests { private Mock _mockProblemDetailsService = null!; private ServiceExceptionHandler _handler = null!; - + [TestInitialize] public void Setup() { _mockProblemDetailsService = new Mock(); _handler = new ServiceExceptionHandler(_mockProblemDetailsService.Object); } - + [TestMethod] public async Task HandleException_WhenBadRequestException_ShouldReturnProblemDetails() { @@ -30,9 +30,9 @@ public async Task HandleException_WhenBadRequestException_ShouldReturnProblemDet x.TryWriteAsync(It.IsAny())) .Callback(context => problemDetailsContext = context) .ReturnsAsync(true); - + await _handler.TryHandleAsync(httpContext, exception, CancellationToken.None); - + Assert.AreEqual((int)HttpStatusCode.BadRequest, httpContext.Response.StatusCode); Assert.IsNotNull(problemDetailsContext); Assert.AreEqual("https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.1", @@ -42,7 +42,7 @@ public async Task HandleException_WhenBadRequestException_ShouldReturnProblemDet Assert.AreEqual(exception, problemDetailsContext.Exception); Assert.AreEqual(exception.Message, problemDetailsContext.ProblemDetails.Detail); } - + [TestMethod] public async Task HandleException_WhenNotFoundException_ShouldReturnProblemDetails() { @@ -50,13 +50,13 @@ public async Task HandleException_WhenNotFoundException_ShouldReturnProblemDetai var exception = new NotFoundException("Resource not found"); ProblemDetailsContext? problemDetailsContext = null; - _mockProblemDetailsService.Setup(x => + _mockProblemDetailsService.Setup(x => x.TryWriteAsync(It.IsAny())) .Callback(context => problemDetailsContext = context) .ReturnsAsync(true); - + await _handler.TryHandleAsync(httpContext, exception, CancellationToken.None); - + Assert.AreEqual((int)HttpStatusCode.NotFound, httpContext.Response.StatusCode); Assert.IsNotNull(problemDetailsContext); Assert.AreEqual("https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.4", @@ -66,7 +66,7 @@ public async Task HandleException_WhenNotFoundException_ShouldReturnProblemDetai Assert.AreEqual(exception, problemDetailsContext.Exception); Assert.AreEqual(exception.Message, problemDetailsContext.ProblemDetails.Detail); } - + [TestMethod] public async Task HandleException_WhenVerificationException_ShouldReturnProblemDetails() { @@ -74,13 +74,13 @@ public async Task HandleException_WhenVerificationException_ShouldReturnProblemD var exception = new VerificationException("Verification error"); ProblemDetailsContext? problemDetailsContext = null; - _mockProblemDetailsService.Setup(x => + _mockProblemDetailsService.Setup(x => x.TryWriteAsync(It.IsAny())) .Callback(context => problemDetailsContext = context) .ReturnsAsync(true); - + await _handler.TryHandleAsync(httpContext, exception, CancellationToken.None); - + Assert.AreEqual((int)HttpStatusCode.BadRequest, httpContext.Response.StatusCode); Assert.IsNotNull(problemDetailsContext); Assert.AreEqual("https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.1", diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Exceptions/ValidationExceptionHandlerTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Exceptions/ValidationExceptionHandlerTests.cs index a2b50a72..9a087bb6 100644 --- a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Exceptions/ValidationExceptionHandlerTests.cs +++ b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Exceptions/ValidationExceptionHandlerTests.cs @@ -12,14 +12,14 @@ public class ValidationExceptionHandlerTests { private Mock _mockProblemDetailsService = null!; private ValidationExceptionHandler _handler = null!; - + [TestInitialize] public void Setup() { _mockProblemDetailsService = new Mock(); _handler = new ValidationExceptionHandler(_mockProblemDetailsService.Object); } - + [TestMethod] public async Task HandleException_WhenValidationException_ShouldReturnProblemDetails() { @@ -35,9 +35,9 @@ public async Task HandleException_WhenValidationException_ShouldReturnProblemDet x.TryWriteAsync(It.IsAny())) .Callback(context => problemDetailsContext = context) .ReturnsAsync(true); - + await _handler.TryHandleAsync(httpContext, exception, CancellationToken.None); - + Assert.AreEqual((int)HttpStatusCode.BadRequest, httpContext.Response.StatusCode); Assert.IsNotNull(problemDetailsContext); Assert.AreEqual("https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.1", @@ -47,7 +47,7 @@ public async Task HandleException_WhenValidationException_ShouldReturnProblemDet Assert.AreEqual(exception, problemDetailsContext.Exception); Assert.AreEqual("One or more validation errors occurred", problemDetailsContext.ProblemDetails.Detail); - + Assert.IsNotNull(problemDetailsContext.ProblemDetails.Extensions); Assert.IsTrue(problemDetailsContext.ProblemDetails.Extensions.ContainsKey("errors")); } diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Services/Authentication/AuthServiceTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Services/Authentication/AuthServiceTests.cs index 78c1a0a1..631dbbde 100644 --- a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Services/Authentication/AuthServiceTests.cs +++ b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Services/Authentication/AuthServiceTests.cs @@ -16,21 +16,21 @@ public class AuthServiceTests private Mock _mockContext = null!; private PasswordHasher _hasher = null!; private AuthService _service = null!; - + [TestInitialize] public void Setup() { _mockContext = new Mock(); _hasher = new PasswordHasher(); _service = new AuthService(_mockContext.Object); - + var user = new User { Email = "jon.snow@castleblack.com", Username = "jsnow", Password = _hasher.HashPassword(null!, "password") }; - + _mockContext.Setup(c => c.Users) .ReturnsDbSet(new List { user }); } @@ -43,9 +43,9 @@ public void Login_WhenUserExistsAndPasswordIsCorrect_ShouldReturnUser() Email = "jon.snow@castleblack.com", Password = "password" }; - + var result = _service.Login(request); - + Assert.IsNotNull(result); Assert.IsInstanceOfType(result, typeof(User)); } @@ -80,10 +80,10 @@ public void Register_WhenUserWithEmailAlreadyExists_ShouldThrowBadRequestExcepti { Email = "jon.snow@castleblack.com" }; - + Assert.ThrowsException(() => _service.Register(request)); } - + [TestMethod] public void Register_WhenUserWithUsernameAlreadyExists_ShouldThrowBadRequestException() { @@ -92,7 +92,7 @@ public void Register_WhenUserWithUsernameAlreadyExists_ShouldThrowBadRequestExce Email = "jon.stark@castleblack.com", Username = "jsnow" }; - + Assert.ThrowsException(() => _service.Register(request)); } @@ -116,9 +116,9 @@ public void Register_WhenUserDoesNotExist_ShouldReturnRegisteredUser() }, Role = "User" }; - + var result = _service.Register(request); - + Assert.IsNotNull(result); Assert.IsInstanceOfType(result, typeof(User)); } diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Services/Authentication/TokenServiceTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Services/Authentication/TokenServiceTests.cs index b2c5a995..99e576fa 100644 --- a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Services/Authentication/TokenServiceTests.cs +++ b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Services/Authentication/TokenServiceTests.cs @@ -16,7 +16,7 @@ public class TokenServiceTests private TokenService _service = null!; private Mock _mockConfiguration = null!; private User _validUser = null!; - + [TestInitialize] public void Setup() { @@ -24,12 +24,12 @@ public void Setup() var bytes = new byte[32]; RandomNumberGenerator.Fill(bytes); - _mockConfiguration.Setup(x => + _mockConfiguration.Setup(x => x["JwtSettings:Key"]).Returns(Convert.ToBase64String(bytes)); - - _mockConfiguration.Setup(x => + + _mockConfiguration.Setup(x => x["JwtSettings:Issuer"]).Returns(IssAudValue); - + var mockSection = new Mock(); var mockAudienceValue = new Mock(); mockAudienceValue.Setup(x => x.Value).Returns(IssAudValue); @@ -37,15 +37,16 @@ public void Setup() x.GetChildren()).Returns(new List { mockAudienceValue.Object }); _mockConfiguration.Setup(x => x.GetSection("JwtSettings:Audiences")).Returns(mockSection.Object); - + var mockDurationValue = new Mock(); mockDurationValue.SetupGet(x => x.Value).Returns(DurationInHours.ToString()); _mockConfiguration.Setup(x => x.GetSection("JwtSettings:DurationInHours")).Returns(mockDurationValue.Object); - + _service = new TokenService(_mockConfiguration.Object); - - _validUser = new User { + + _validUser = new User + { Id = 1, Name = "Jon", Surname = "Snow", @@ -58,7 +59,7 @@ public void Setup() public void GenerateToken_WhenValidUser_ShouldReturnTokenPayload() { var result = _service.GenerateToken(_validUser); - + Assert.IsNotNull(result); Assert.AreEqual("Bearer", result.TokenType); Assert.IsNotNull(result.AccessToken); @@ -69,10 +70,10 @@ public void GenerateToken_WhenValidUser_ShouldReturnTokenPayload() public void GenerateToken_WhenValidUser_ShouldReturnValidToken() { var result = _service.GenerateToken(_validUser); - + var tokenHandler = new JwtSecurityTokenHandler(); var token = tokenHandler.ReadToken(result.AccessToken) as JwtSecurityToken; - + Assert.IsNotNull(token); Assert.AreEqual(IssAudValue, token.Issuer); Assert.AreEqual(IssAudValue, token.Audiences.First()); diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/AddressValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/AddressValidatorTests.cs index f4a89585..c81d582c 100644 --- a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/AddressValidatorTests.cs +++ b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/AddressValidatorTests.cs @@ -7,13 +7,13 @@ namespace ReasnAPI.Tests.UnitTests.Validators; public class AddressValidatorTests { private AddressValidator _validator = null!; - + [TestInitialize] public void Setup() { _validator = new AddressValidator(); } - + [TestMethod] public void Validate_WhenValidRequest_ShouldReturnTrue() { @@ -26,14 +26,18 @@ public void Validate_WhenValidRequest_ShouldReturnTrue() ZipCode = "12345" }; var result = _validator.Validate(request); - + Assert.IsTrue(result.IsValid); } - + [TestMethod] public void Validate_WhenEmptyStreet_ShouldReturnFalse() { - var request = new AddressDto { Street = "" }; + var request = new AddressDto + { + Street = "" + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); @@ -41,16 +45,20 @@ public void Validate_WhenEmptyStreet_ShouldReturnFalse() e => e.ErrorMessage == "'Street' must not be empty." )); } - + [TestMethod] public void Validate_WhenStreetTooLong_ShouldReturnFalse() { - var request = new AddressDto { Street = new string('a', 65) }; + var request = new AddressDto + { + Street = new string('a', 65) + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); Assert.IsTrue(result.Errors.Exists( - e => e.ErrorMessage == + e => e.ErrorMessage == "The length of 'Street' must be 64 characters or fewer. You entered 65 characters." )); } @@ -58,19 +66,27 @@ public void Validate_WhenStreetTooLong_ShouldReturnFalse() [TestMethod] public void Validate_WhenInvalidStreet_ShouldReturnFalse() { - var request = new AddressDto { Street = "The Wall!" }; + var request = new AddressDto + { + Street = "The Wall!" + }; + var result = _validator.Validate(request); - + Assert.IsFalse(result.IsValid); Assert.IsTrue(result.Errors.Exists( e => e.ErrorMessage == "'Street' is not in the correct format." )); } - + [TestMethod] public void Validate_WhenEmptyCity_ShouldReturnFalse() { - var request = new AddressDto { City = "" }; + var request = new AddressDto + { + City = "" + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); @@ -78,36 +94,48 @@ public void Validate_WhenEmptyCity_ShouldReturnFalse() e => e.ErrorMessage == "'City' must not be empty." )); } - + [TestMethod] public void Validate_WhenCityTooLong_ShouldReturnFalse() { - var request = new AddressDto { City = new string('a', 65) }; + var request = new AddressDto + { + City = new string('a', 65) + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); Assert.IsTrue(result.Errors.Exists( - e => e.ErrorMessage == + e => e.ErrorMessage == "The length of 'City' must be 64 characters or fewer. You entered 65 characters." )); } - + [TestMethod] public void Validate_WhenInvalidCity_ShouldReturnFalse() { - var request = new AddressDto { City = "Castle Black!" }; + var request = new AddressDto + { + City = "Castle Black!" + }; + var result = _validator.Validate(request); - + Assert.IsFalse(result.IsValid); Assert.IsTrue(result.Errors.Exists( e => e.ErrorMessage == "'City' is not in the correct format." )); } - + [TestMethod] public void Validate_WhenEmptyCountry_ShouldReturnFalse() { - var request = new AddressDto { Country = "" }; + var request = new AddressDto + { + Country = "" + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); @@ -115,11 +143,15 @@ public void Validate_WhenEmptyCountry_ShouldReturnFalse() e => e.ErrorMessage == "'Country' must not be empty." )); } - + [TestMethod] public void Validate_WhenCountryTooLong_ShouldReturnFalse() { - var request = new AddressDto { Country = new string('a', 65) }; + var request = new AddressDto + { + Country = new string('a', 65) + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); @@ -132,7 +164,11 @@ public void Validate_WhenCountryTooLong_ShouldReturnFalse() [TestMethod] public void Validate_WhenInvalidCountry_ShouldReturnFalse() { - var request = new AddressDto { Country = "Westeros!" }; + var request = new AddressDto + { + Country = "Westeros!" + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); @@ -140,11 +176,15 @@ public void Validate_WhenInvalidCountry_ShouldReturnFalse() e => e.ErrorMessage == "'Country' is not in the correct format." )); } - + [TestMethod] public void Validate_WhenEmptyState_ShouldReturnFalse() { - var request = new AddressDto { State = "" }; + var request = new AddressDto + { + State = "" + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); @@ -152,11 +192,15 @@ public void Validate_WhenEmptyState_ShouldReturnFalse() e => e.ErrorMessage == "'State' must not be empty." )); } - + [TestMethod] public void Validate_WhenStateTooLong_ShouldReturnFalse() { - var request = new AddressDto { State = new string('a', 65) }; + var request = new AddressDto + { + State = new string('a', 65) + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); @@ -165,38 +209,50 @@ public void Validate_WhenStateTooLong_ShouldReturnFalse() "The length of 'State' must be 64 characters or fewer. You entered 65 characters." )); } - + [TestMethod] public void Validate_WhenInvalidState_ShouldReturnFalse() { - var request = new AddressDto { State = "The North!" }; + var request = new AddressDto + { + State = "The North!" + }; + var result = _validator.Validate(request); - + Assert.IsFalse(result.IsValid); Assert.IsTrue(result.Errors.Exists( e => e.ErrorMessage == "'State' is not in the correct format." )); } - + [TestMethod] public void Validate_WhenZipCodeTooLong_ShouldReturnFalse() { - var request = new AddressDto { ZipCode = new string('a', 9) }; + var request = new AddressDto + { + ZipCode = new string('a', 9) + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); Assert.IsTrue(result.Errors.Exists( - e => e.ErrorMessage == + e => e.ErrorMessage == "The length of 'Zip Code' must be 8 characters or fewer. You entered 9 characters." )); } - + [TestMethod] public void Validate_WhenInvalidZipCode_ShouldReturnFalse() { - var request = new AddressDto { ZipCode = "12345!" }; + var request = new AddressDto + { + ZipCode = "12345!" + }; + var result = _validator.Validate(request); - + Assert.IsFalse(result.IsValid); Assert.IsTrue(result.Errors.Exists( e => e.ErrorMessage == "'Zip Code' is not in the correct format." diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/Authentication/LoginRequestValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/Authentication/LoginRequestValidatorTests.cs index d1c2b67a..971de2cc 100644 --- a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/Authentication/LoginRequestValidatorTests.cs +++ b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/Authentication/LoginRequestValidatorTests.cs @@ -18,7 +18,12 @@ public void Setup() [TestMethod] public void Validate_WhenValidRequest_ShouldReturnTrue() { - var request = new LoginRequest { Email = "test@example.com", Password = "password" }; + var request = new LoginRequest + { + Email = "test@example.com", + Password = "password" + }; + var result = _validator.Validate(request); Assert.IsTrue(result.IsValid); @@ -27,7 +32,11 @@ public void Validate_WhenValidRequest_ShouldReturnTrue() [TestMethod] public void Validate_WhenEmptyEmail_ShouldReturnFalse() { - var request = new LoginRequest { Email = "", Password = "password" }; + var request = new LoginRequest + { + Email = "", + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); @@ -39,7 +48,11 @@ public void Validate_WhenEmptyEmail_ShouldReturnFalse() [TestMethod] public void Validate_WhenInvalidEmail_ShouldReturnFalse() { - var request = new LoginRequest { Email = "invalid email", Password = "password" }; + var request = new LoginRequest + { + Email = "invalid email" + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); @@ -51,7 +64,11 @@ public void Validate_WhenInvalidEmail_ShouldReturnFalse() [TestMethod] public void Validate_WhenEmptyPassword_ShouldReturnFalse() { - var request = new LoginRequest { Email = "test@example.com", Password = "" }; + var request = new LoginRequest + { + Password = "" + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/Authentication/RegisterRequestValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/Authentication/RegisterRequestValidatorTests.cs index 7ab00d5e..c866983a 100644 --- a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/Authentication/RegisterRequestValidatorTests.cs +++ b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/Authentication/RegisterRequestValidatorTests.cs @@ -8,7 +8,7 @@ namespace ReasnAPI.Tests.UnitTests.Validators.Authentication; public class RegisterRequestValidatorTests { private RegisterRequestValidator _validator = null!; - + [TestInitialize] public void Setup() { @@ -36,14 +36,18 @@ public void Validate_WhenValidRequest_ShouldReturnTrue() Role = "User" }; var result = _validator.Validate(request); - + Assert.IsTrue(result.IsValid); } [TestMethod] public void Validate_WhenEmptyName_ShouldReturnFalse() { - var request = new RegisterRequest { Name = "" }; + var request = new RegisterRequest + { + Name = "" + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); @@ -51,25 +55,33 @@ public void Validate_WhenEmptyName_ShouldReturnFalse() e => e.ErrorMessage == "'Name' must not be empty." )); } - + [TestMethod] public void Validate_WhenNameTooLong_ShouldReturnFalse() { - var request = new RegisterRequest { Name = new string('a', 65) }; + var request = new RegisterRequest + { + Name = new string('a', 65) + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); Console.WriteLine(result.Errors[0]); Assert.IsTrue(result.Errors.Exists( - e => e.ErrorMessage == + e => e.ErrorMessage == "The length of 'Name' must be 64 characters or fewer. You entered 65 characters." )); } - + [TestMethod] public void Validate_WhenInvalidName_ShouldReturnFalse() { - var request = new RegisterRequest { Name = "123" }; + var request = new RegisterRequest + { + Name = "123" + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); @@ -78,11 +90,15 @@ public void Validate_WhenInvalidName_ShouldReturnFalse() e => e.ErrorMessage == "'Name' is not in the correct format." )); } - + [TestMethod] public void Validate_WhenEmptySurname_ShouldReturnFalse() { - var request = new RegisterRequest { Surname = "" }; + var request = new RegisterRequest + { + Surname = "" + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); @@ -90,24 +106,32 @@ public void Validate_WhenEmptySurname_ShouldReturnFalse() e => e.ErrorMessage == "'Surname' must not be empty." )); } - + [TestMethod] public void Validate_WhenSurnameTooLong_ShouldReturnFalse() { - var request = new RegisterRequest { Surname = new string('a', 65) }; + var request = new RegisterRequest + { + Surname = new string('a', 65) + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); Assert.IsTrue(result.Errors.Exists( - e => e.ErrorMessage == + e => e.ErrorMessage == "The length of 'Surname' must be 64 characters or fewer. You entered 65 characters." )); } - + [TestMethod] public void Validate_WhenInvalidSurname_ShouldReturnFalse() { - var request = new RegisterRequest { Surname = "123" }; + var request = new RegisterRequest + { + Surname = "123" + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); @@ -115,11 +139,15 @@ public void Validate_WhenInvalidSurname_ShouldReturnFalse() e => e.ErrorMessage == "'Surname' is not in the correct format." )); } - + [TestMethod] public void Validate_WhenEmptyUsername_ShouldReturnFalse() { - var request = new RegisterRequest { Username = "" }; + var request = new RegisterRequest + { + Username = "" + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); @@ -127,24 +155,32 @@ public void Validate_WhenEmptyUsername_ShouldReturnFalse() e => e.ErrorMessage == "'Username' must not be empty." )); } - + [TestMethod] public void Validate_WhenUsernameTooLong_ShouldReturnFalse() { - var request = new RegisterRequest { Username = new string('a', 65) }; + var request = new RegisterRequest + { + Username = new string('a', 65) + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); Assert.IsTrue(result.Errors.Exists( - e => e.ErrorMessage == + e => e.ErrorMessage == "The length of 'Username' must be 64 characters or fewer. You entered 65 characters." )); } - + [TestMethod] public void Validate_WhenInvalidUsername_ShouldReturnFalse() { - var request = new RegisterRequest { Username = "user name" }; + var request = new RegisterRequest + { + Username = "user name" + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); @@ -152,11 +188,15 @@ public void Validate_WhenInvalidUsername_ShouldReturnFalse() e => e.ErrorMessage == "'Username' is not in the correct format." )); } - + [TestMethod] public void Validate_WhenEmptyEmail_ShouldReturnFalse() { - var request = new RegisterRequest { Email = "" }; + var request = new RegisterRequest + { + Email = "" + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); @@ -164,24 +204,32 @@ public void Validate_WhenEmptyEmail_ShouldReturnFalse() e => e.ErrorMessage == "'Email' must not be empty." )); } - + [TestMethod] public void Validate_WhenEmailTooLong_ShouldReturnFalse() { - var request = new RegisterRequest { Email = new string('a', 256) }; + var request = new RegisterRequest + { + Email = new string('a', 256) + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); Assert.IsTrue(result.Errors.Exists( - e => e.ErrorMessage == + e => e.ErrorMessage == "The length of 'Email' must be 255 characters or fewer. You entered 256 characters." )); } - + [TestMethod] public void Validate_WhenInvalidEmail_ShouldReturnFalse() { - var request = new RegisterRequest { Email = "invalid email" }; + var request = new RegisterRequest + { + Email = "invalid email" + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); @@ -189,11 +237,15 @@ public void Validate_WhenInvalidEmail_ShouldReturnFalse() e => e.ErrorMessage == "'Email' is not a valid email address." )); } - + [TestMethod] public void Validate_WhenEmptyPassword_ShouldReturnFalse() { - var request = new RegisterRequest { Password = "" }; + var request = new RegisterRequest + { + Password = "" + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); @@ -201,36 +253,33 @@ public void Validate_WhenEmptyPassword_ShouldReturnFalse() e => e.ErrorMessage == "'Password' must not be empty." )); } - + [TestMethod] public void Validate_WhenInvalidPassword_ShouldReturnFalse() { - var request = new RegisterRequest { Password = "password" }; + var request = new RegisterRequest + { + Password = "password" + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); Assert.IsTrue(result.Errors.Exists( - e => e.ErrorMessage == + e => e.ErrorMessage == "Password must contain at least one uppercase letter, " + "one lowercase letter, one number, and be at least 6 characters long." )); } - - [TestMethod] - public void Validate_WhenEmptyPhone_ShouldReturnTrue() - { - var request = new RegisterRequest { Phone = "" }; - var result = _validator.Validate(request); - Assert.IsFalse(result.Errors.Exists( - e => e.ErrorMessage == "'Phone' is not in the correct format." - )); - } - [TestMethod] public void Validate_WhenInvalidPhone_ShouldReturnFalse() { - var request = new RegisterRequest { Phone = "invalid phone" }; + var request = new RegisterRequest + { + Phone = "invalid phone" + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); @@ -239,11 +288,15 @@ public void Validate_WhenInvalidPhone_ShouldReturnFalse() e => e.ErrorMessage == "'Phone' is not in the correct format." )); } - + [TestMethod] public void Validate_WhenEmptyAddress_ShouldReturnFalse() { - var request = new RegisterRequest { Address = null }; + var request = new RegisterRequest + { + Address = null! + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); @@ -251,11 +304,15 @@ public void Validate_WhenEmptyAddress_ShouldReturnFalse() e => e.ErrorMessage == "'Address' must not be empty." )); } - + [TestMethod] public void Validate_WhenEmptyRole_ShouldReturnFalse() { - var request = new RegisterRequest { Role = "" }; + var request = new RegisterRequest + { + Role = "" + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); @@ -267,7 +324,11 @@ public void Validate_WhenEmptyRole_ShouldReturnFalse() [TestMethod] public void Validate_WhenInvalidRole_ShouldReturnFalse() { - var request = new RegisterRequest { Role = "invalid role" }; + var request = new RegisterRequest + { + Role = "invalid role" + }; + var result = _validator.Validate(request); Assert.IsFalse(result.IsValid); diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/CommentValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/CommentValidatorTests.cs new file mode 100644 index 00000000..b1134ebf --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/CommentValidatorTests.cs @@ -0,0 +1,63 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.UnitTests.Validators; + +[TestClass] +public class CommentValidatorTests +{ + private CommentValidator _validator = null!; + + [TestInitialize] + public void Setup() + { + _validator = new CommentValidator(); + } + + [TestMethod] + public void Validate_WhenCommentIsValid_ShouldReturnTrue() + { + var comment = new CommentDto + { + Content = "Content", + CreatedAt = DateTime.UtcNow + }; + + var result = _validator.Validate(comment); + + Assert.IsTrue(result.IsValid); + } + + [TestMethod] + public void Validate_WhenContentIsEmpty_ShouldReturnFalse() + { + var comment = new CommentDto + { + Content = "" + }; + + var result = _validator.Validate(comment); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Content' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenContentIsTooLong_ShouldReturnFalse() + { + var comment = new CommentDto + { + Content = new string('a', 1025) + }; + + var result = _validator.Validate(comment); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == + "The length of 'Content' must be 1024 characters or fewer. You entered 1025 characters." + )); + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/EventValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/EventValidatorTests.cs new file mode 100644 index 00000000..e7533a31 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/EventValidatorTests.cs @@ -0,0 +1,208 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Models.Enums; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.UnitTests.Validators; + +[TestClass] +public class EventValidatorTests +{ + private EventValidator _validator = null!; + + [TestInitialize] + public void Setup() + { + _validator = new EventValidator(); + } + + [TestMethod] + public void Validate_WhenEventIsValid_ShouldReturnTrue() + { + var eventDto = new EventDto + { + Name = "Event", + Description = "Description", + StartAt = DateTime.UtcNow, + EndAt = DateTime.UtcNow.AddDays(1), + CreatedAt = DateTime.UtcNow, + UpdatedAt = DateTime.UtcNow, + Slug = "the-slug", + Status = EventStatus.Approved + }; + + var result = _validator.Validate(eventDto); + + Assert.IsTrue(result.IsValid); + } + + [TestMethod] + public void Validate_WhenNameIsEmpty_ShouldReturnFalse() + { + var eventDto = new EventDto + { + Name = "" + }; + + var result = _validator.Validate(eventDto); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Name' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenNameIsTooLong_ShouldReturnFalse() + { + var eventDto = new EventDto + { + Name = new string('a', 65) + }; + + var result = _validator.Validate(eventDto); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == + "The length of 'Name' must be 64 characters or fewer. You entered 65 characters." + )); + } + + [TestMethod] + public void Validate_WhenDescriptionIsEmpty_ShouldReturnFalse() + { + var eventDto = new EventDto + { + Description = "" + }; + + var result = _validator.Validate(eventDto); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Description' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenDescriptionIsTooLong_ShouldReturnFalse() + { + var eventDto = new EventDto + { + Description = new string('a', 4049) + }; + + var result = _validator.Validate(eventDto); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == + "The length of 'Description' must be 4048 characters or fewer. You entered 4049 characters." + )); + } + + [TestMethod] + public void Validate_WhenStartAtIsAfterEndAt_ShouldReturnFalse() + { + var eventDto = new EventDto + { + StartAt = DateTime.UtcNow, + EndAt = DateTime.UtcNow.AddDays(-1) + }; + + var result = _validator.Validate(eventDto); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'StartAt' must be before 'EndAt'." + )); + } + + [TestMethod] + public void Validate_WhenSlugIsEmpty_ShouldReturnFalse() + { + var eventDto = new EventDto + { + Slug = "" + }; + + var result = _validator.Validate(eventDto); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Slug' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenSlugIsTooLong_ShouldReturnFalse() + { + var eventDto = new EventDto + { + Slug = new string('a', 129) + }; + + var result = _validator.Validate(eventDto); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == + "The length of 'Slug' must be 128 characters or fewer. You entered 129 characters." + )); + } + + [TestMethod] + public void Validate_WhenInvalidSlug_ShouldReturnFalse() + { + var eventDto = new EventDto + { + Slug = "the-slug!" + }; + + var result = _validator.Validate(eventDto); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Slug' is not in the correct format." + )); + } + + [TestMethod] + public void Validate_WhenTagsAreInvalid_ShouldReturnFalse() + { + var eventDto = new EventDto + { + Tags = new List + { + new() { Name = "" } + } + }; + + var result = _validator.Validate(eventDto); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Name' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenParametersAreInvalid_ShouldReturnFalse() + { + var eventDto = new EventDto + { + Parameters = new List + { + new() { Key = "", Value = "" } + } + }; + + var result = _validator.Validate(eventDto); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Key' must not be empty." + )); + } + +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/InterestValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/InterestValidatorTests.cs new file mode 100644 index 00000000..8c7a2ba9 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/InterestValidatorTests.cs @@ -0,0 +1,78 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.UnitTests.Validators; + +[TestClass] +public class InterestValidatorTests +{ + private InterestValidator _validator = null!; + + [TestInitialize] + public void Setup() + { + _validator = new InterestValidator(); + } + + [TestMethod] + public void Validate_WhenInterestIsValid_ShouldReturnTrue() + { + var interest = new InterestDto + { + Name = "Interest" + }; + + var result = _validator.Validate(interest); + + Assert.IsTrue(result.IsValid); + } + + [TestMethod] + public void Validate_WhenNameIsEmpty_ShouldReturnFalse() + { + var interest = new InterestDto + { + Name = "" + }; + + var result = _validator.Validate(interest); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Name' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenNameIsTooLong_ShouldReturnFalse() + { + var interest = new InterestDto + { + Name = new string('a', 33) + }; + + var result = _validator.Validate(interest); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == + "The length of 'Name' must be 32 characters or fewer. You entered 33 characters." + )); + } + + [TestMethod] + public void Validate_WhenInvalidName_ShouldReturnFalse() + { + var interest = new InterestDto + { + Name = "123" + }; + + var result = _validator.Validate(interest); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Name' is not in the correct format." + )); + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/ParameterValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/ParameterValidatorTests.cs new file mode 100644 index 00000000..4f77c778 --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/ParameterValidatorTests.cs @@ -0,0 +1,128 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.UnitTests.Validators; + +[TestClass] +public class ParameterValidatorTests +{ + private ParameterValidator _validator = null!; + + [TestInitialize] + public void Setup() + { + _validator = new ParameterValidator(); + } + + [TestMethod] + public void Validate_WhenParameterIsValid_ShouldReturnTrue() + { + var parameter = new ParameterDto + { + Key = "Key", + Value = "Value" + }; + + var result = _validator.Validate(parameter); + + Assert.IsTrue(result.IsValid); + } + + [TestMethod] + public void Validate_WhenKeyIsEmpty_ShouldReturnFalse() + { + var parameter = new ParameterDto + { + Key = "" + }; + + var result = _validator.Validate(parameter); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Key' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenKeyIsTooLong_ShouldReturnFalse() + { + var parameter = new ParameterDto + { + Key = new string('a', 33) + }; + + var result = _validator.Validate(parameter); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == + "The length of 'Key' must be 32 characters or fewer. You entered 33 characters." + )); + } + + [TestMethod] + public void Validate_WhenInvalidKey_ShouldReturnFalse() + { + var parameter = new ParameterDto + { + Key = "123" + }; + + var result = _validator.Validate(parameter); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Key' is not in the correct format." + )); + } + + [TestMethod] + public void Validate_WhenValueIsEmpty_ShouldReturnFalse() + { + var parameter = new ParameterDto + { + Value = "" + }; + + var result = _validator.Validate(parameter); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Value' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenValueIsTooLong_ShouldReturnFalse() + { + var parameter = new ParameterDto + { + Value = new string('a', 65) + }; + + var result = _validator.Validate(parameter); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == + "The length of 'Value' must be 64 characters or fewer. You entered 65 characters." + )); + } + + [TestMethod] + public void Validate_WhenInvalidValue_ShouldReturnFalse() + { + var parameter = new ParameterDto + { + Value = "Not a valid value!" + }; + + var result = _validator.Validate(parameter); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Value' is not in the correct format." + )); + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/TagValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/TagValidatorTests.cs new file mode 100644 index 00000000..8f0097eb --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/TagValidatorTests.cs @@ -0,0 +1,78 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.UnitTests.Validators; + +[TestClass] +public class TagValidatorTests +{ + private TagValidator _validator = null!; + + [TestInitialize] + public void Setup() + { + _validator = new TagValidator(); + } + + [TestMethod] + public void Validate_WhenTagIsValid_ShouldReturnTrue() + { + var tag = new TagDto + { + Name = "Tag" + }; + + var result = _validator.Validate(tag); + + Assert.IsTrue(result.IsValid); + } + + [TestMethod] + public void Validate_WhenNameIsEmpty_ShouldReturnFalse() + { + var tag = new TagDto + { + Name = "" + }; + + var result = _validator.Validate(tag); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Name' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenNameIsTooLong_ShouldReturnFalse() + { + var tag = new TagDto + { + Name = new string('a', 65) + }; + + var result = _validator.Validate(tag); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == + "The length of 'Name' must be 64 characters or fewer. You entered 65 characters." + )); + } + + [TestMethod] + public void Validate_WhenNameContainsInvalidCharacters_ShouldReturnFalse() + { + var tag = new TagDto + { + Name = "123" + }; + + var result = _validator.Validate(tag); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Name' is not in the correct format." + )); + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/UserValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/UserValidatorTests.cs new file mode 100644 index 00000000..508ea1ef --- /dev/null +++ b/Server/ReasnAPI/ReasnAPI.Tests/UnitTests/Validators/UserValidatorTests.cs @@ -0,0 +1,247 @@ +using ReasnAPI.Models.DTOs; +using ReasnAPI.Models.Enums; +using ReasnAPI.Validators; + +namespace ReasnAPI.Tests.UnitTests.Validators; + +[TestClass] +public class UserValidatorTests +{ + private UserValidator _validator = null!; + + [TestInitialize] + public void Setup() + { + _validator = new UserValidator(); + } + + [TestMethod] + public void Validate_WhenValidRequest_ShouldReturnTrue() + { + var user = new UserDto + { + Name = "Jon", + Surname = "Snow", + Email = "jon.snow@castleblack.com", + Username = "jonSnow", + Phone = "+123 456789", + Role = UserRole.User + }; + + var result = _validator.Validate(user); + + Assert.IsTrue(result.IsValid); + } + + [TestMethod] + public void Validate_WhenEmptyName_ShouldReturnFalse() + { + var user = new UserDto + { + Name = "" + }; + + var result = _validator.Validate(user); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Name' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenNameTooLong_ShouldReturnFalse() + { + var user = new UserDto + { + Name = new string('a', 65) + }; + + var result = _validator.Validate(user); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == + "The length of 'Name' must be 64 characters or fewer. You entered 65 characters." + )); + } + + [TestMethod] + public void Validate_WhenInvalidName_ShouldReturnFalse() + { + var user = new UserDto + { + Name = "123" + }; + + var result = _validator.Validate(user); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Name' is not in the correct format." + )); + } + + [TestMethod] + public void Validate_WhenEmptySurname_ShouldReturnFalse() + { + var user = new UserDto + { + Surname = "" + }; + + var result = _validator.Validate(user); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Surname' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenSurnameTooLong_ShouldReturnFalse() + { + var user = new UserDto + { + Surname = new string('a', 65) + }; + + var result = _validator.Validate(user); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == + "The length of 'Surname' must be 64 characters or fewer. You entered 65 characters." + )); + } + + [TestMethod] + public void Validate_WhenInvalidSurname_ShouldReturnFalse() + { + var user = new UserDto + { + Surname = "123" + }; + + var result = _validator.Validate(user); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Surname' is not in the correct format." + )); + } + + [TestMethod] + public void Validate_WhenEmptyEmail_ShouldReturnFalse() + { + var user = new UserDto + { + Email = "" + }; + + var result = _validator.Validate(user); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Email' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenEmailTooLong_ShouldReturnFalse() + { + var user = new UserDto + { + Email = new string('a', 256) + }; + + var result = _validator.Validate(user); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == + "The length of 'Email' must be 255 characters or fewer. You entered 256 characters." + )); + } + + [TestMethod] + public void Validate_WhenInvalidEmail_ShouldReturnFalse() + { + var user = new UserDto + { + Email = "jon.snow" + }; + + var result = _validator.Validate(user); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Email' is not a valid email address." + )); + } + + [TestMethod] + public void Validate_WhenEmptyUsername_ShouldReturnFalse() + { + var user = new UserDto + { + Username = "" + }; + + var result = _validator.Validate(user); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Username' must not be empty." + )); + } + + [TestMethod] + public void Validate_WhenUsernameTooLong_ShouldReturnFalse() + { + var user = new UserDto + { + Username = new string('a', 65) + }; + + var result = _validator.Validate(user); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == + "The length of 'Username' must be 64 characters or fewer. You entered 65 characters." + )); + } + + [TestMethod] + public void Validate_WhenInvalidUsername_ShouldReturnFalse() + { + var user = new UserDto + { + Username = "user name" + }; + + var result = _validator.Validate(user); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Username' is not in the correct format." + )); + } + + [TestMethod] + public void Validate_WhenInvalidPhone_ShouldReturnFalse() + { + var user = new UserDto + { + Phone = "123" + }; + + var result = _validator.Validate(user); + + Assert.IsFalse(result.IsValid); + Assert.IsTrue(result.Errors.Exists( + e => e.ErrorMessage == "'Phone' is not in the correct format." + )); + } +} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs deleted file mode 100644 index 2f714be0..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/CommentValidatorTests.cs +++ /dev/null @@ -1,65 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class CommentValidatorTests - { - [TestMethod] - public void Validate_WhenContentIsEmpty_ReturnsValidationResult() - { - var comment = new CommentDto - { - Content = "", - CreatedAt = DateTime.Now - }; - - var result = CommentValidator.Validate(comment); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Content is required")); - } - - [TestMethod] - public void Validate_WhenContentIsTooLong_ReturnsValidationResult() - { - var comment = new CommentDto - { - Content = new string('a', 1025), - CreatedAt = DateTime.Now - }; - - var result = CommentValidator.Validate(comment); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Content is too long")); - } - - [TestMethod] - public void Validate_WhenCreatedAtIsInTheFuture_ReturnsValidationResult() - { - var comment = new CommentDto - { - Content = "Content", - CreatedAt = DateTime.Now.AddMinutes(1) - }; - - var result = CommentValidator.Validate(comment); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "CreatedAt is in the future")); - } - - [TestMethod] - public void Validate_WhenCommentIsValid_ReturnsNoValidationResult() - { - var comment = new CommentDto - { - Content = "Content", - CreatedAt = DateTime.Now - }; - - var result = CommentValidator.Validate(comment); - - Assert.IsFalse(result.Any()); - } - } -} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs deleted file mode 100644 index 06da3702..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/EventValidatorTests.cs +++ /dev/null @@ -1,271 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Models.Enums; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class EventValidatorTests - { - [TestMethod] - public void Validate_WhenNameIsEmpty_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "", - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now.AddMinutes(1), - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "slug", - Status = EventStatus.Completed - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); - } - - [TestMethod] - public void Validate_WhenNameIsTooLong_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = new string('a', 65), - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now.AddMinutes(1), - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "slug", - Status = EventStatus.WaitingForApproval - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); - } - - [TestMethod] - public void Validate_WhenNameIsValid_ReturnsNoValidationResult() - { - var event1 = new EventDto - { - Name = "ValidName", - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now.AddMinutes(1), - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "slug", - Status = EventStatus.Inprogress - }; - - var result = EventValidator.Validate(event1); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenDescriptionIsEmpty_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "", - StartAt = DateTime.Now, - EndAt = DateTime.Now.AddMinutes(1), - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "slug", - Status = EventStatus.Inprogress - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Description is required")); - } - - [TestMethod] - public void Validate_WhenDescriptionIsTooLong_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = new string('a', 4049), - StartAt = DateTime.Now, - EndAt = DateTime.Now.AddMinutes(1), - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "slug", - Status = EventStatus.Approved - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Description is too long")); - } - - [TestMethod] - public void Validate_WhenDescriptionIsValid_ReturnsNoValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "Valid Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now.AddMinutes(1), - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "slug", - Status = EventStatus.WaitingForApproval - }; - - var result = EventValidator.Validate(event1); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenStartAtIsAfterEndAt_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "Description", - StartAt = DateTime.Now.AddMinutes(1), - EndAt = DateTime.Now, - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "slug", - Status = EventStatus.Completed - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "StartTime is after EndTime")); - } - - [TestMethod] - public void Validate_WhenCreatedAtIsInTheFuture_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now.AddMinutes(1), - CreatedAt = DateTime.Now.AddMinutes(1), - UpdatedAt = DateTime.Now, - Slug = "slug", - Status = EventStatus.Inprogress - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "CreatedAt is in the future")); - } - - [TestMethod] - public void Validate_WhenUpdatedAtIsInTheFuture_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now.AddMinutes(1), - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now.AddMinutes(1), - Slug = "slug", - Status = EventStatus.WaitingForApproval - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "UpdatedAt is in the future")); - } - - [TestMethod] - public void Validate_WhenSlugIsEmpty_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now.AddMinutes(1), - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "", - Status = EventStatus.Inprogress - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is invalid")); - } - - [TestMethod] - public void Validate_WhenSlugIsTooLong_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now.AddMinutes(1), - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = new string('a', 129), - Status = EventStatus.WaitingForApproval - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is too long")); - } - - [TestMethod] - public void Validate_WhenSlugIsIsInvalid_ReturnsValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now.AddMinutes(1), - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "invalid slug", - Status = EventStatus.Completed - }; - - var result = EventValidator.Validate(event1); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Slug is invalid")); - } - - [TestMethod] - public void Validate_WhenSlugIsValid_ReturnsNoValidationResult() - { - var event1 = new EventDto - { - Name = "Name", - Description = "Description", - StartAt = DateTime.Now, - EndAt = DateTime.Now.AddMinutes(1), - CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now, - Slug = "valid-slug", - Status = EventStatus.Inprogress - }; - - var result = EventValidator.Validate(event1); - - Assert.IsFalse(result.Any()); - } - } -} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs deleted file mode 100644 index 1b7b2242..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/InterestValidatorTests.cs +++ /dev/null @@ -1,62 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class InterestValidatorTests - { - [TestMethod] - public void Validate_WhenNameIsEmpty_ReturnsValidationResult() - { - var interest = new InterestDto - { - Name = "" - }; - - var result = InterestValidator.Validate(interest); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsTooLong_ReturnsValidationResult() - { - var interest = new InterestDto - { - Name = new string('a', 33) - }; - - var result = InterestValidator.Validate(interest); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); - } - - [TestMethod] - public void Validate_WhenNameIsInvalid_ReturnsValidationResult() - { - var interest = new InterestDto - { - Name = "Invalid Name" - }; - - var result = InterestValidator.Validate(interest); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsValid_ReturnsNoValidationResult() - { - var interest = new InterestDto - { - Name = "Valid Name" - }; - - var result = InterestValidator.Validate(interest); - - Assert.IsFalse(result.Any()); - } - } -} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs deleted file mode 100644 index 601f69ed..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/ParameterValidatorTests.cs +++ /dev/null @@ -1,109 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class ParameterValidatorTests - { - [TestMethod] - public void Validate_WhenKeyIsEmpty_ReturnsKeyIsRequired() - { - var parameter = new ParameterDto - { - Key = "", - Value = "value" - }; - - var result = ParameterValidator.Validate(parameter); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is invalid")); - } - - [TestMethod] - public void Validate_WhenKeyIsTooLong_ReturnsKeyIsTooLong() - { - var parameter = new ParameterDto - { - Key = new string('a', 33), - Value = "value" - }; - - var result = ParameterValidator.Validate(parameter); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is too long")); - } - - [TestMethod] - public void Validate_WhenKeyIsInvalid_ReturnsKeyIsInvalid() - { - var parameter = new ParameterDto - { - Key = "Invalid Key", - Value = "value" - }; - - var result = ParameterValidator.Validate(parameter); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Key is invalid")); - } - - [TestMethod] - public void Validate_WhenValueIsEmpty_ReturnsValueIsRequired() - { - var parameter = new ParameterDto - { - Key = "key", - Value = "" - }; - - var result = ParameterValidator.Validate(parameter); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is invalid")); - } - - [TestMethod] - public void Validate_WhenValueIsTooLong_ReturnsValueIsTooLong() - { - var parameter = new ParameterDto - { - Key = "key", - Value = new string('a', 65) - }; - - var result = ParameterValidator.Validate(parameter); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is too long")); - } - - [TestMethod] - public void Validate_WhenValueIsInvalid_ReturnsValueIsInvalid() - { - var parameter = new ParameterDto - { - Key = "key", - Value = "Invalid Value" - }; - - var result = ParameterValidator.Validate(parameter); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Value is invalid")); - } - - [TestMethod] - public void Validate_WhenValueAndKeyAreValid_ReturnsNoValidationResult() - { - var parameter = new ParameterDto - { - Key = "key", - Value = "value" - }; - - var result = ParameterValidator.Validate(parameter); - - Assert.IsFalse(result.Any()); - } - } -} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs deleted file mode 100644 index 98b163b3..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/TagValidatorTests.cs +++ /dev/null @@ -1,62 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class TagValidatorTests - { - [TestMethod] - public void Validate_WhenNameIsEmpty_ReturnsValidationResult() - { - var tag = new TagDto - { - Name = "" - }; - - var result = TagValidator.Validate(tag); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsTooLong_ReturnsValidationResult() - { - var tag = new TagDto - { - Name = new string('a', 65) - }; - - var result = TagValidator.Validate(tag); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); - } - - [TestMethod] - public void Validate_WhenNameIsInvalid_ReturnsValidationResult() - { - var tag = new TagDto - { - Name = "Invalid Name" - }; - - var result = TagValidator.Validate(tag); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsValid_ReturnsValidationResult() - { - var tag = new TagDto - { - Name = "Valid Name" - }; - - var result = TagValidator.Validate(tag); - - Assert.IsFalse(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - } -} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs b/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs deleted file mode 100644 index 33aa6c54..00000000 --- a/Server/ReasnAPI/ReasnAPI.Tests/Validators/UserValidatorTests.cs +++ /dev/null @@ -1,375 +0,0 @@ -using ReasnAPI.Models.DTOs; -using ReasnAPI.Models.Enums; -using ReasnAPI.Validators; - -namespace ReasnAPI.Tests.Validators -{ - [TestClass] - public class UserValidatorTests - { - [TestMethod] - public void Validate_WhenNameIsEmpty_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "", - Surname = "Surname", - Username = "Username", - Role = UserRole.User, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsTooLong_ReturnsValidationResult() - { - var user = new UserDto - { - Name = new string('a', 65), - Surname = "Surname", - Username = "Username", - Role = UserRole.User, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is too long")); - } - - [TestMethod] - public void Validate_WhenNameIsInvalid_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Invalid Name", - Surname = "Surname", - Username = "Username", - Role = UserRole.User, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Name is invalid")); - } - - [TestMethod] - public void Validate_WhenNameIsValid_ReturnsNoValidationResult() - { - var user = new UserDto - { - Name = "Validname", - Surname = "Surname", - Username = "Username", - Role = UserRole.User, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenSurnameIsEmpty_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "", - Username = "Username", - Role = UserRole.User, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is invalid")); - } - - [TestMethod] - public void Validate_WhenSurnameIsTooLong_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = new string('a', 65), - Username = "Username", - Role = UserRole.User, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is too long")); - } - - [TestMethod] - public void Validate_WhenSurnameIsInvalid_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Invalid Surname", - Username = "Username", - Role = UserRole.User, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Surname is invalid")); - } - - [TestMethod] - public void Validate_WhenSurnameIsValid_ReturnsNoValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Validsurname", - Username = "Username", - Role = UserRole.User, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenUsernameIsEmpty_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "", - Role = UserRole.User, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is invalid")); - } - - [TestMethod] - public void Validate_WhenUsernameIsTooLong_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = new string('a', 65), - Role = UserRole.User, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is too long")); - } - - [TestMethod] - public void Validate_WhenUsernameIsInvalid_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "Invalid Username", - Role = UserRole.User, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Username is invalid")); - } - - [TestMethod] - public void Validate_WhenUsernameIsValid_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "ValidUsername", - Role = UserRole.User, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenEmailIsEmpty_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "Username", - Role = UserRole.User, - Email = "", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is required")); - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is invalid")); - } - - [TestMethod] - public void Validate_WhenEmailIsTooLong_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "Username", - Role = UserRole.User, - Email = new string('a', 256), - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is too long")); - } - - [TestMethod] - public void Validate_WhenEmailIsInvalid_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "Username", - Role = UserRole.User, - Email = "Invalid Email", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Email is invalid")); - } - - [TestMethod] - public void Validate_WhenEmailIsValid_ReturnsNoValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "Username", - Role = UserRole.User, - Email = "valid@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsFalse(result.Any()); - } - - [TestMethod] - public void Validate_WhenPhoneIsTooLong_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "Username", - Role = UserRole.User, - Email = "email@email.com", - AddressId = 1, - Phone = new string('a', 20) - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Phone is too long")); - } - - [TestMethod] - public void Validate_WhenPhoneIsInvalid_ReturnsValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "Username", - Role = UserRole.User, - Email = "email@email.com", - AddressId = 1, - Phone = "Invalid Phone" - }; - - var result = UserValidator.Validate(user); - - Assert.IsTrue(result.Any(r => r.ErrorMessage == "Phone is invalid")); - } - - [TestMethod] - public void Validate_WhenPhoneIsValid_ReturnsNoValidationResult() - { - var user = new UserDto - { - Name = "Name", - Surname = "Surname", - Username = "Username", - Role = UserRole.User, - Email = "email@email.com", - AddressId = 1, - Phone = "+48 123456789" - }; - - var result = UserValidator.Validate(user); - - Assert.IsFalse(result.Any()); - } - } -} \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs index 6f9640be..3e3b7611 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs @@ -7,22 +7,22 @@ public class AddressValidator : AbstractValidator { public AddressValidator() { - RuleFor(r => r.Country) + RuleFor(a => a.Country) .NotEmpty() .MaximumLength(64) - .Matches(@"^\p{Lu}\p{Ll}+(?:(\s|-)(\p{Lu}\p{Ll}+|i|of|and|the)){0,5}$"); + .Matches(@"^\p{Lu}[\p{L}\s'-]*(? r.City) + RuleFor(a => a.City) .NotEmpty() .MaximumLength(64) - .Matches(@"^\p{Lu}\p{Ll}+(?:(\s|-)\p{Lu}\p{Ll}+)*$"); + .Matches(@"^\p{Lu}[\p{Ll}'.]+(?:[\s-][\p{L}'.]+)*$"); - RuleFor(r => r.Street) + RuleFor(a => a.Street) .NotEmpty() .MaximumLength(64) - .Matches(@"^[\p{L}\d]+(?:(\s)\p{L}+)*(\s(?:(\d+\p{L}?(/\d*\p{L}?)?)))?$"); + .Matches(@"^[\p{L}\d\s\-/.,#']+(? r.State) + RuleFor(a => a.State) .NotEmpty() .MaximumLength(64) .Matches(@"^\p{Lu}\p{Ll}+(?:(\s|-)\p{L}+)*$"); diff --git a/Server/ReasnAPI/ReasnAPI/Validators/Authentication/LoginRequestValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/Authentication/LoginRequestValidator.cs index 09a625d6..2fdc9c99 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/Authentication/LoginRequestValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/Authentication/LoginRequestValidator.cs @@ -7,11 +7,11 @@ public class LoginRequestValidator : AbstractValidator { public LoginRequestValidator() { - RuleFor(r => r.Email) + RuleFor(lr => lr.Email) .NotEmpty() .EmailAddress(); - RuleFor(r => r.Password) + RuleFor(lr => lr.Password) .NotEmpty(); } } \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/Authentication/RegisterRequestValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/Authentication/RegisterRequestValidator.cs index 585b8007..fb8dfeb2 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/Authentication/RegisterRequestValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/Authentication/RegisterRequestValidator.cs @@ -11,17 +11,17 @@ public RegisterRequestValidator() RuleFor(r => r.Name) .NotEmpty() .MaximumLength(64) - .Matches(@"^\p{Lu}\p{Ll}+$"); + .Matches(@"^\p{Lu}[\p{Ll}\s'-]+$"); RuleFor(r => r.Surname) .NotEmpty() .MaximumLength(64) - .Matches(@"^\p{L}+(?:[\s'-]?\p{L}+)*$"); + .Matches(@"^\p{L}+(?:[\s'-]\p{L}+)*$"); RuleFor(r => r.Username) .NotEmpty() .MaximumLength(64) - .Matches(@"^[\p{L}\d._%+-]+$"); + .Matches(@"^[\p{L}\d._%+-]{4,}$"); RuleFor(r => r.Email) .NotEmpty() diff --git a/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs index f0d7efe8..b3b8a2c5 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs @@ -1,28 +1,14 @@ using ReasnAPI.Models.DTOs; -using System.ComponentModel.DataAnnotations; +using FluentValidation; -namespace ReasnAPI.Validators +namespace ReasnAPI.Validators; + +public class CommentValidator : AbstractValidator { - public class CommentValidator : IValidator + public CommentValidator() { - private const int ContentMaxLength = 1024; - - public static IEnumerable Validate(CommentDto comment) - { - if (string.IsNullOrWhiteSpace(comment.Content)) - { - yield return new ValidationResult("Content is required", [nameof(comment.Content)]); - } - - if (comment.Content.Length > ContentMaxLength) - { - yield return new ValidationResult("Content is too long", [nameof(comment.Content)]); - } - - if (comment.CreatedAt >= DateTime.Now) - { - yield return new ValidationResult("CreatedAt is in the future", [nameof(comment.CreatedAt)]); - } - } + RuleFor(c => c.Content) + .NotEmpty() + .MaximumLength(1024); } -} \ No newline at end of file +} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs index d313de3f..7d087ee0 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs @@ -1,67 +1,35 @@ using ReasnAPI.Models.DTOs; -using System.ComponentModel.DataAnnotations; -using System.Text.RegularExpressions; +using FluentValidation; -namespace ReasnAPI.Validators +namespace ReasnAPI.Validators; + +public class EventValidator : AbstractValidator { - public class EventValidator : IValidator + public EventValidator() { - private const int NameMaxLength = 64; - private const int DescriptionMaxLength = 4048; - private const int SlugMaxLength = 128; - private const string SlugRegexPattern = "^[\\p{L}\\d]+[\\p{L}\\d-]*$"; - - public static IEnumerable Validate(EventDto eventData) - { - if (string.IsNullOrWhiteSpace(eventData.Name)) - { - yield return new ValidationResult("Name is required", [nameof(eventData.Name)]); - } - - if (eventData.Name.Length > NameMaxLength) - { - yield return new ValidationResult("Name is too long", [nameof(eventData.Name)]); - } - - if (string.IsNullOrWhiteSpace(eventData.Description)) - { - yield return new ValidationResult("Description is required", [nameof(eventData.Description)]); - } - - if (eventData.Description.Length > DescriptionMaxLength) - { - yield return new ValidationResult("Description is too long", [nameof(eventData.Description)]); - } - - if (eventData.StartAt > eventData.EndAt) - { - yield return new ValidationResult("StartTime is after EndTime", [nameof(eventData.StartAt)]); - } - - if (eventData.CreatedAt >= DateTime.Now) - { - yield return new ValidationResult("CreatedAt is in the future", [nameof(eventData.CreatedAt)]); - } - - if (eventData.UpdatedAt >= DateTime.Now) - { - yield return new ValidationResult("UpdatedAt is in the future", [nameof(eventData.UpdatedAt)]); - } - - if (string.IsNullOrWhiteSpace(eventData.Slug)) - { - yield return new ValidationResult("Slug is required", [nameof(eventData.Slug)]); - } - - if (eventData.Slug.Length > SlugMaxLength) - { - yield return new ValidationResult("Slug is too long", [nameof(eventData.Slug)]); - } - - if (!new Regex(SlugRegexPattern).IsMatch(eventData.Slug)) - { - yield return new ValidationResult("Slug is invalid", [nameof(eventData.Name)]); - } - } + RuleFor(e => e.Name) + .NotEmpty() + .MaximumLength(64); + + RuleFor(e => e.Description) + .NotEmpty() + .MaximumLength(4048); + + RuleFor(e => e.StartAt) + .LessThan(e => e.EndAt) + .WithMessage("'StartAt' must be before 'EndAt'."); + + RuleFor(e => e.Slug) + .NotEmpty() + .MaximumLength(128) + .Matches(@"^[\p{L}\d]+[\p{L}\d-]*$"); + + RuleForEach(e => e.Tags) + .SetValidator(new TagValidator()) + .When(e => e.Tags?.Count > 0); + + RuleForEach(e => e.Parameters) + .SetValidator(new ParameterValidator()) + .When(e => e.Parameters?.Count > 0); } } \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/IValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/IValidator.cs deleted file mode 100644 index 12db5b9b..00000000 --- a/Server/ReasnAPI/ReasnAPI/Validators/IValidator.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace ReasnAPI.Validators -{ - public interface IValidator - { - static abstract IEnumerable Validate(T objectToValidate); - } -} diff --git a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs index cfcb76f5..b7db499c 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs @@ -1,30 +1,15 @@ using ReasnAPI.Models.DTOs; -using System.ComponentModel.DataAnnotations; -using System.Text.RegularExpressions; +using FluentValidation; -namespace ReasnAPI.Validators +namespace ReasnAPI.Validators; + +public class InterestValidator : AbstractValidator { - public class InterestValidator : IValidator + public InterestValidator() { - private const int NameMaxLength = 32; - private const string NameRegexPattern = "^\\p{Lu}\\p{Ll}+(?:\\s\\p{L}+)*$"; - - public static IEnumerable Validate(InterestDto interest) - { - if (string.IsNullOrWhiteSpace(interest.Name)) - { - yield return new ValidationResult("Name is required", [nameof(interest.Name)]); - } - - if (interest.Name.Length > NameMaxLength) - { - yield return new ValidationResult("Name is too long", [nameof(interest.Name)]); - } - - if (!new Regex(NameRegexPattern).IsMatch(interest.Name)) - { - yield return new ValidationResult("Name is invalid", [nameof(interest.Name)]); - } - } + RuleFor(i => i.Name) + .NotEmpty() + .MaximumLength(32) + .Matches(@"^\p{Lu}\p{Ll}+(?:\s\p{L}+)*$"); } } \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs index 4dca0be0..b8ae96ae 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs @@ -1,47 +1,20 @@ using ReasnAPI.Models.DTOs; -using System.ComponentModel.DataAnnotations; -using System.Text.RegularExpressions; +using FluentValidation; -namespace ReasnAPI.Validators +namespace ReasnAPI.Validators; + +public class ParameterValidator : AbstractValidator { - public class ParameterValidator : IValidator + public ParameterValidator() { - private const int KeyMaxLength = 32; - private const string KeyRegexPattern = "^\\p{L}+(?:\\s\\p{L}+)*$"; - private const int ValueMaxLength = 64; - private const string ValueRegexPattern = "^[\\p{L}\\d]+(?:\\s[\\p{L}\\d]+)*$"; - - public static IEnumerable Validate(ParameterDto parameter) - { - if (string.IsNullOrWhiteSpace(parameter.Key)) - { - yield return new ValidationResult("Key is required", [nameof(parameter.Key)]); - } - - if (parameter.Key.Length > KeyMaxLength) - { - yield return new ValidationResult("Key is too long", [nameof(parameter.Key)]); - } - - if (!new Regex(KeyRegexPattern).IsMatch(parameter.Key)) - { - yield return new ValidationResult("Key is invalid", [nameof(parameter.Key)]); - } - - if (string.IsNullOrWhiteSpace(parameter.Value)) - { - yield return new ValidationResult("Value is required", [nameof(parameter.Value)]); - } - - if (parameter.Value.Length > ValueMaxLength) - { - yield return new ValidationResult("Value is too long", [nameof(parameter.Value)]); - } + RuleFor(p => p.Key) + .NotEmpty() + .MaximumLength(32) + .Matches(@"^\p{L}+(?:\s\p{L}+)*$"); - if (!new Regex(ValueRegexPattern).IsMatch(parameter.Value)) - { - yield return new ValidationResult("Value is invalid", [nameof(parameter.Value)]); - } - } + RuleFor(p => p.Value) + .NotEmpty() + .MaximumLength(64) + .Matches(@"^[\p{L}\d]+(?:\s[\p{L}\d]+)*$"); } } \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs index 1691512d..0ce02f41 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs @@ -1,30 +1,15 @@ using ReasnAPI.Models.DTOs; -using System.ComponentModel.DataAnnotations; -using System.Text.RegularExpressions; +using FluentValidation; -namespace ReasnAPI.Validators +namespace ReasnAPI.Validators; + +public class TagValidator : AbstractValidator { - public class TagValidator : IValidator + public TagValidator() { - private const int NameMaxLength = 64; - private const string NameRegexPattern = "^\\p{L}+(?:\\s\\p{L}+)*$"; - - public static IEnumerable Validate(TagDto tag) - { - if (string.IsNullOrWhiteSpace(tag.Name)) - { - yield return new ValidationResult("Name is required", [nameof(tag.Name)]); - } - - if (tag.Name.Length > NameMaxLength) - { - yield return new ValidationResult("Name is too long", [nameof(tag.Name)]); - } - - if (!new Regex(NameRegexPattern).IsMatch(tag.Name)) - { - yield return new ValidationResult("Name is invalid", [nameof(tag.Name)]); - } - } + RuleFor(t => t.Name) + .NotEmpty() + .MaximumLength(64) + .Matches(@"^\p{L}+(?:\s\p{L}+)*$"); } } \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs index 7d13bc16..32295a0f 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs @@ -1,96 +1,34 @@ using ReasnAPI.Models.DTOs; -using System.ComponentModel.DataAnnotations; -using System.Text.RegularExpressions; +using FluentValidation; -namespace ReasnAPI.Validators +namespace ReasnAPI.Validators; + +public class UserValidator : AbstractValidator { - public class UserValidator : IValidator + public UserValidator() { - private const int NameMaxLength = 64; - private const string NameRegexPattern = "^\\p{Lu}\\p{Ll}+$"; - private const int SurnameMaxLength = 64; - private const string SurnameRegexPattern = "^\\p{L}+(?:[\\s'-]?\\p{L}+)*$"; - private const int UsernameMaxLength = 64; - private const string UsernameRegexPattern = "^[\\p{L}\\d._%+-]+$"; - private const int EmailMaxLength = 255; - private const string EmailRegexPattern = "^[a-zA-Z\\d._%+-]+@[a-zA-Z\\d.-]+\\.[a-zA-Z]{2,6}$"; - private const int PhoneMaxLength = 16; - private const string PhoneRegexPattern = "^\\+\\d{1,3}\\s\\d{1,15}$"; - - public static IEnumerable Validate(UserDto user) - { - if (string.IsNullOrWhiteSpace(user.Name)) - { - yield return new ValidationResult("Name is required", [nameof(user.Name)]); - } - - if (user.Name.Length > NameMaxLength) - { - yield return new ValidationResult("Name is too long", [nameof(user.Name)]); - } - - if (!new Regex(NameRegexPattern).IsMatch(user.Name)) - { - yield return new ValidationResult("Name is invalid", [nameof(user.Name)]); - } - - if (string.IsNullOrWhiteSpace(user.Surname)) - { - yield return new ValidationResult("Surname is required", [nameof(user.Surname)]); - } - - if (user.Surname.Length > SurnameMaxLength) - { - yield return new ValidationResult("Surname is too long", [nameof(user.Surname)]); - } - - if (!new Regex(SurnameRegexPattern).IsMatch(user.Surname)) - { - yield return new ValidationResult("Surname is invalid", [nameof(user.Surname)]); - } - - if (string.IsNullOrWhiteSpace(user.Username)) - { - yield return new ValidationResult("Username is required", [nameof(user.Username)]); - } - - if (user.Username.Length > UsernameMaxLength) - { - yield return new ValidationResult("Username is too long", [nameof(user.Username)]); - } - - if (!new Regex(UsernameRegexPattern).IsMatch(user.Username)) - { - yield return new ValidationResult("Username is invalid", [nameof(user.Username)]); - } - - if (string.IsNullOrWhiteSpace(user.Email)) - { - yield return new ValidationResult("Email is required", [nameof(user.Email)]); - } - - if (user.Email.Length > EmailMaxLength) - { - yield return new ValidationResult("Email is too long", [nameof(user.Email)]); - } - - if (!new Regex(EmailRegexPattern).IsMatch(user.Email)) - { - yield return new ValidationResult("Email is invalid", [nameof(user.Email)]); - } - - if (!string.IsNullOrWhiteSpace(user.Phone)) - { - if (user.Phone.Length > PhoneMaxLength) - { - yield return new ValidationResult("Phone is too long", [nameof(user.Phone)]); - } - - if (!new Regex(PhoneRegexPattern).IsMatch(user.Phone)) - { - yield return new ValidationResult("Phone is invalid", [nameof(user.Phone)]); - } - } - } + RuleFor(r => r.Name) + .NotEmpty() + .MaximumLength(64) + .Matches(@"^\p{Lu}[\p{Ll}\s'-]+$"); + + RuleFor(r => r.Surname) + .NotEmpty() + .MaximumLength(64) + .Matches(@"^\p{L}+(?:[\s'-]\p{L}+)*$"); + + RuleFor(r => r.Username) + .NotEmpty() + .MaximumLength(64) + .Matches(@"^[\p{L}\d._%+-]{4,}$"); + + RuleFor(r => r.Email) + .NotEmpty() + .MaximumLength(255) + .EmailAddress(); + + RuleFor(r => r.Phone) + .Matches(@"^\+\d{1,3}\s\d{1,15}$") + .When(r => !string.IsNullOrEmpty(r.Phone)); } } \ No newline at end of file From 8a25fe80e2614a628cade7dec3483eb2467cac3b Mon Sep 17 00:00:00 2001 From: raczu Date: Thu, 6 Jun 2024 00:47:21 +0200 Subject: [PATCH 24/24] refactor: make regexes and length variables as constants --- .../ReasnAPI/Validators/AddressValidator.cs | 32 +++++++++++++------ .../RegisterRequestValidator.cs | 29 +++++++++++------ .../ReasnAPI/Validators/CommentValidator.cs | 4 ++- .../ReasnAPI/Validators/EventValidator.cs | 16 +++++++--- .../ReasnAPI/Validators/InterestValidator.cs | 8 +++-- .../ReasnAPI/Validators/ParameterValidator.cs | 14 +++++--- .../ReasnAPI/Validators/TagValidator.cs | 8 +++-- .../ReasnAPI/Validators/UserValidator.cs | 26 ++++++++++----- 8 files changed, 96 insertions(+), 41 deletions(-) diff --git a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs index 3e3b7611..6f2b2efb 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs @@ -5,31 +5,43 @@ namespace ReasnAPI.Validators; public class AddressValidator : AbstractValidator { + private const int MaxCountryLength = 64; + private const int MaxCityLength = 64; + private const int MaxStreetLength = 64; + private const int MaxStateLength = 64; + private const int MaxZipCodeLength = 8; + + private const string CountryRegex = @"^\p{Lu}[\p{L}\s'-]*(? a.Country) .NotEmpty() - .MaximumLength(64) - .Matches(@"^\p{Lu}[\p{L}\s'-]*(? a.City) .NotEmpty() - .MaximumLength(64) - .Matches(@"^\p{Lu}[\p{Ll}'.]+(?:[\s-][\p{L}'.]+)*$"); + .MaximumLength(MaxCityLength) + .Matches(CityRegex); RuleFor(a => a.Street) .NotEmpty() - .MaximumLength(64) - .Matches(@"^[\p{L}\d\s\-/.,#']+(? a.State) .NotEmpty() - .MaximumLength(64) - .Matches(@"^\p{Lu}\p{Ll}+(?:(\s|-)\p{L}+)*$"); + .MaximumLength(MaxStateLength) + .Matches(StateRegex); RuleFor(r => r.ZipCode) - .MaximumLength(8) - .Matches(@"^[\p{L}\d\s-]{3,}$") + .MaximumLength(MaxZipCodeLength) + .Matches(ZipCodeRegex) .When(r => !string.IsNullOrEmpty(r.ZipCode)); } } \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/Authentication/RegisterRequestValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/Authentication/RegisterRequestValidator.cs index fb8dfeb2..255dfc93 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/Authentication/RegisterRequestValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/Authentication/RegisterRequestValidator.cs @@ -6,37 +6,48 @@ namespace ReasnAPI.Validators.Authentication; public class RegisterRequestValidator : AbstractValidator { + private const int MaxNameLength = 64; + private const int MaxSurnameLength = 64; + private const int MaxUsernameLength = 64; + private const int MaxEmailLength = 255; + + private const string NameRegex = @"^\p{Lu}[\p{Ll}\s'-]+$"; + private const string SurnameRegex = @"^\p{L}+(?:[\s'-]\p{L}+)*$"; + private const string UsernameRegex = @"^[\p{L}\d._%+-]{4,}$"; + private const string PasswordRegex = @"^((?=\S*?[A-Z])(?=\S*?[a-z])(?=\S*?[0-9]).{6,})\S$"; + private const string PhoneRegex = @"^\+\d{1,3}\s\d{1,15}$"; + public RegisterRequestValidator() { RuleFor(r => r.Name) .NotEmpty() - .MaximumLength(64) - .Matches(@"^\p{Lu}[\p{Ll}\s'-]+$"); + .MaximumLength(MaxNameLength) + .Matches(NameRegex); RuleFor(r => r.Surname) .NotEmpty() - .MaximumLength(64) - .Matches(@"^\p{L}+(?:[\s'-]\p{L}+)*$"); + .MaximumLength(MaxSurnameLength) + .Matches(SurnameRegex); RuleFor(r => r.Username) .NotEmpty() - .MaximumLength(64) - .Matches(@"^[\p{L}\d._%+-]{4,}$"); + .MaximumLength(MaxUsernameLength) + .Matches(UsernameRegex); RuleFor(r => r.Email) .NotEmpty() - .MaximumLength(255) + .MaximumLength(MaxEmailLength) .EmailAddress(); RuleFor(r => r.Password) .NotEmpty() - .Matches(@"^((?=\S*?[A-Z])(?=\S*?[a-z])(?=\S*?[0-9]).{6,})\S$") + .Matches(PasswordRegex) .WithMessage( "Password must contain at least one uppercase letter, " + "one lowercase letter, one number, and be at least 6 characters long."); RuleFor(r => r.Phone) - .Matches(@"^\+\d{1,3}\s\d{1,15}$") + .Matches(PhoneRegex) .When(r => !string.IsNullOrEmpty(r.Phone)); RuleFor(r => r.Address) diff --git a/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs index b3b8a2c5..9c2ce1aa 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/CommentValidator.cs @@ -5,10 +5,12 @@ namespace ReasnAPI.Validators; public class CommentValidator : AbstractValidator { + private const int MaxContentLength = 1024; + public CommentValidator() { RuleFor(c => c.Content) .NotEmpty() - .MaximumLength(1024); + .MaximumLength(MaxContentLength); } } diff --git a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs index 7d087ee0..bc4d4d51 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/EventValidator.cs @@ -5,15 +5,21 @@ namespace ReasnAPI.Validators; public class EventValidator : AbstractValidator { + private const int MaxNameLength = 64; + private const int MaxDescriptionLength = 4048; + private const int MaxSlugLength = 128; + + private const string SlugRegex = @"^[\p{L}\d]+[\p{L}\d-]*$"; + public EventValidator() { RuleFor(e => e.Name) .NotEmpty() - .MaximumLength(64); + .MaximumLength(MaxNameLength); RuleFor(e => e.Description) .NotEmpty() - .MaximumLength(4048); + .MaximumLength(MaxDescriptionLength); RuleFor(e => e.StartAt) .LessThan(e => e.EndAt) @@ -21,9 +27,9 @@ public EventValidator() RuleFor(e => e.Slug) .NotEmpty() - .MaximumLength(128) - .Matches(@"^[\p{L}\d]+[\p{L}\d-]*$"); - + .MaximumLength(MaxSlugLength) + .Matches(SlugRegex); + RuleForEach(e => e.Tags) .SetValidator(new TagValidator()) .When(e => e.Tags?.Count > 0); diff --git a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs index b7db499c..2b485429 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/InterestValidator.cs @@ -5,11 +5,15 @@ namespace ReasnAPI.Validators; public class InterestValidator : AbstractValidator { + private const int MaxNameLength = 32; + + private const string NameRegex = @"^\p{Lu}\p{Ll}+(?:\s\p{L}+)*$"; + public InterestValidator() { RuleFor(i => i.Name) .NotEmpty() - .MaximumLength(32) - .Matches(@"^\p{Lu}\p{Ll}+(?:\s\p{L}+)*$"); + .MaximumLength(MaxNameLength) + .Matches(NameRegex); } } \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs index b8ae96ae..54894136 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/ParameterValidator.cs @@ -5,16 +5,22 @@ namespace ReasnAPI.Validators; public class ParameterValidator : AbstractValidator { + private const int MaxKeyLength = 32; + private const int MaxValueLength = 64; + + private const string KeyRegex = @"^\p{L}+(?:\s\p{L}+)*$"; + private const string ValueRegex = @"^[\p{L}\d]+(?:\s[\p{L}\d]+)*$"; + public ParameterValidator() { RuleFor(p => p.Key) .NotEmpty() - .MaximumLength(32) - .Matches(@"^\p{L}+(?:\s\p{L}+)*$"); + .MaximumLength(MaxKeyLength) + .Matches(KeyRegex); RuleFor(p => p.Value) .NotEmpty() - .MaximumLength(64) - .Matches(@"^[\p{L}\d]+(?:\s[\p{L}\d]+)*$"); + .MaximumLength(MaxValueLength) + .Matches(ValueRegex); } } \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs index 0ce02f41..641ab05a 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/TagValidator.cs @@ -5,11 +5,15 @@ namespace ReasnAPI.Validators; public class TagValidator : AbstractValidator { + private const int MaxNameLength = 64; + + private const string NameRegex = @"^\p{L}+(?:\s\p{L}+)*$"; + public TagValidator() { RuleFor(t => t.Name) .NotEmpty() - .MaximumLength(64) - .Matches(@"^\p{L}+(?:\s\p{L}+)*$"); + .MaximumLength(MaxNameLength) + .Matches(NameRegex); } } \ No newline at end of file diff --git a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs index 32295a0f..fa072029 100644 --- a/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs +++ b/Server/ReasnAPI/ReasnAPI/Validators/UserValidator.cs @@ -5,30 +5,40 @@ namespace ReasnAPI.Validators; public class UserValidator : AbstractValidator { + private const int MaxNameLength = 64; + private const int MaxSurnameLength = 64; + private const int MaxUsernameLength = 64; + private const int MaxEmailLength = 255; + + private const string NameRegex = @"^\p{Lu}[\p{Ll}\s'-]+$"; + private const string SurnameRegex = @"^\p{L}+(?:[\s'-]\p{L}+)*$"; + private const string UsernameRegex = @"^[\p{L}\d._%+-]{4,}$"; + private const string PhoneRegex = @"^\+\d{1,3}\s\d{1,15}$"; + public UserValidator() { RuleFor(r => r.Name) .NotEmpty() - .MaximumLength(64) - .Matches(@"^\p{Lu}[\p{Ll}\s'-]+$"); + .MaximumLength(MaxNameLength) + .Matches(NameRegex); RuleFor(r => r.Surname) .NotEmpty() - .MaximumLength(64) - .Matches(@"^\p{L}+(?:[\s'-]\p{L}+)*$"); + .MaximumLength(MaxSurnameLength) + .Matches(SurnameRegex); RuleFor(r => r.Username) .NotEmpty() - .MaximumLength(64) - .Matches(@"^[\p{L}\d._%+-]{4,}$"); + .MaximumLength(MaxUsernameLength) + .Matches(UsernameRegex); RuleFor(r => r.Email) .NotEmpty() - .MaximumLength(255) + .MaximumLength(MaxEmailLength) .EmailAddress(); RuleFor(r => r.Phone) - .Matches(@"^\+\d{1,3}\s\d{1,15}$") + .Matches(PhoneRegex) .When(r => !string.IsNullOrEmpty(r.Phone)); } } \ No newline at end of file