From 812906e2f05088b13dca6142726ea2ac37baead5 Mon Sep 17 00:00:00 2001 From: Stephanie Buadu <47737608+acn-sbuad@users.noreply.github.com> Date: Tue, 18 Jun 2024 08:20:56 +0200 Subject: [PATCH] latest notifications validation logic (#107) --- .../EmailNotificationOrderRequestValidator.cs | 34 +++++++++++---- .../SmsNotificationOrderRequestValidator.cs | 42 +++++++++++++------ .../API/Validators/ValidationConstants.cs | 18 ++++++++ 3 files changed, 72 insertions(+), 22 deletions(-) create mode 100644 src/Notifications/API/Validators/ValidationConstants.cs diff --git a/src/Notifications/API/Validators/EmailNotificationOrderRequestValidator.cs b/src/Notifications/API/Validators/EmailNotificationOrderRequestValidator.cs index 8552995b..4b77149e 100644 --- a/src/Notifications/API/Validators/EmailNotificationOrderRequestValidator.cs +++ b/src/Notifications/API/Validators/EmailNotificationOrderRequestValidator.cs @@ -17,15 +17,31 @@ public class EmailNotificationOrderRequestValidator : AbstractValidator order.Recipients) - .NotEmpty() - .WithMessage("One or more recipient is required.") - .Must(recipients => recipients.TrueForAll(a => - { - return - (!string.IsNullOrWhiteSpace(a.EmailAddress) && IsValidEmail(a.EmailAddress)) || - (!string.IsNullOrWhiteSpace(a.OrganizationNumber) ^ !string.IsNullOrWhiteSpace(a.NationalIdentityNumber)); - })) - .WithMessage("Either a valid email address, organization number, or national identity number must be provided for each recipient."); + .NotEmpty() + .WithMessage("One or more recipient is required."); + + RuleForEach(order => order.Recipients) + .ChildRules(recipient => + { + recipient.RuleFor(r => r) + .Must(r => !string.IsNullOrEmpty(r.EmailAddress) || !string.IsNullOrEmpty(r.OrganizationNumber) || !string.IsNullOrEmpty(r.NationalIdentityNumber)) + .WithMessage("Either a valid email address, organization number, or national identity number must be provided for each recipient."); + + recipient.RuleFor(r => r.EmailAddress) + .Must(email => IsValidEmail(email)) + .When(r => !string.IsNullOrEmpty(r.EmailAddress)) + .WithMessage("Invalid email address format."); + + recipient.RuleFor(a => a.NationalIdentityNumber) + .Must(nin => nin?.Length == ValidationConstants.NationalIdentityNumberLength && nin.All(char.IsDigit)) + .When(r => !string.IsNullOrEmpty(r.NationalIdentityNumber)) + .WithMessage($"National identity number must be {ValidationConstants.NationalIdentityNumberLength} digits long."); + + recipient.RuleFor(a => a.OrganizationNumber) + .Must(on => on?.Length == ValidationConstants.OrganizationNumberLength && on.All(char.IsDigit)) + .When(r => !string.IsNullOrEmpty(r.OrganizationNumber)) + .WithMessage($"Organization number must be {ValidationConstants.OrganizationNumberLength} digits long."); + }); RuleFor(order => order.RequestedSendTime) .Must(sendTime => sendTime.Kind != DateTimeKind.Unspecified) diff --git a/src/Notifications/API/Validators/SmsNotificationOrderRequestValidator.cs b/src/Notifications/API/Validators/SmsNotificationOrderRequestValidator.cs index 425d7e97..a7a38f2e 100644 --- a/src/Notifications/API/Validators/SmsNotificationOrderRequestValidator.cs +++ b/src/Notifications/API/Validators/SmsNotificationOrderRequestValidator.cs @@ -16,21 +16,37 @@ public class SmsNotificationOrderRequestValidator : AbstractValidator order.Recipients) - .NotEmpty() - .WithMessage("One or more recipient is required.") - .Must(recipients => recipients.TrueForAll(a => - { - return - (!string.IsNullOrWhiteSpace(a.MobileNumber) && MobileNumberHelper.IsValidMobileNumber(a.MobileNumber)) || - (!string.IsNullOrWhiteSpace(a.OrganizationNumber) ^ !string.IsNullOrWhiteSpace(a.NationalIdentityNumber)); - })) - .WithMessage("Either a valid mobile number starting with country code, organization number, or national identity number must be provided for each recipient."); + .NotEmpty() + .WithMessage("One or more recipient is required."); + + RuleForEach(order => order.Recipients) + .ChildRules(recipient => + { + recipient.RuleFor(r => r) + .Must(r => !string.IsNullOrEmpty(r.MobileNumber) || !string.IsNullOrEmpty(r.OrganizationNumber) || !string.IsNullOrEmpty(r.NationalIdentityNumber)) + .WithMessage("Either a valid mobile number starting with country code, organization number, or national identity number must be provided for each recipient."); + + recipient.RuleFor(r => r.MobileNumber) + .Must(mobileNumber => MobileNumberHelper.IsValidMobileNumber(mobileNumber)) + .When(r => !string.IsNullOrEmpty(r.MobileNumber)) + .WithMessage("Invalid mobile number format."); + + recipient.RuleFor(a => a.NationalIdentityNumber) + .Must(nin => nin?.Length == ValidationConstants.NationalIdentityNumberLength && nin.All(char.IsDigit)) + .When(r => !string.IsNullOrEmpty(r.NationalIdentityNumber)) + .WithMessage($"National identity number must be {ValidationConstants.NationalIdentityNumberLength} digits long."); + + recipient.RuleFor(a => a.OrganizationNumber) + .Must(on => on?.Length == ValidationConstants.OrganizationNumberLength && on.All(char.IsDigit)) + .When(r => !string.IsNullOrEmpty(r.OrganizationNumber)) + .WithMessage($"Organization number must be {ValidationConstants.OrganizationNumberLength} digits long."); + }); RuleFor(order => order.RequestedSendTime) - .Must(sendTime => sendTime.Kind != DateTimeKind.Unspecified) - .WithMessage("The requested send time value must have specified a time zone.") - .Must(sendTime => sendTime >= DateTime.UtcNow.AddMinutes(-5)) - .WithMessage("Send time must be in the future. Leave blank to send immediately."); + .Must(sendTime => sendTime.Kind != DateTimeKind.Unspecified) + .WithMessage("The requested send time value must have specified a time zone.") + .Must(sendTime => sendTime >= DateTime.UtcNow.AddMinutes(-5)) + .WithMessage("Send time must be in the future. Leave blank to send immediately."); RuleFor(order => order.Body).NotEmpty(); } diff --git a/src/Notifications/API/Validators/ValidationConstants.cs b/src/Notifications/API/Validators/ValidationConstants.cs new file mode 100644 index 00000000..ff07046f --- /dev/null +++ b/src/Notifications/API/Validators/ValidationConstants.cs @@ -0,0 +1,18 @@ +namespace Altinn.Notifications.Validators +{ + /// + /// Class comprised of all shared validation constants + /// + public static class ValidationConstants + { + /// + /// Required lenth for a national identity number + /// + public const int NationalIdentityNumberLength = 11; + + /// + /// Required length for an organization number + /// + public const int OrganizationNumberLength = 9; + } +}