From 7abb05391406a8ed29645db117afecf1c976946e Mon Sep 17 00:00:00 2001
From: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
Date: Fri, 16 Jul 2021 08:01:51 +1000
Subject: [PATCH] Refactor email attributes (#1458)
* Add StrictEmailAddress attribute
* Remove duplicate checks, use attributes instead
* Rename EmailAddressListAttribute
---
.../Request/MemberCreateRequestModel.cs | 20 +++----------
.../Api/Request/Accounts/EmailRequestModel.cs | 3 +-
.../Request/Accounts/RegisterRequestModel.cs | 3 +-
.../OrganizationUserRequestModels.cs | 2 +-
.../Providers/ProviderUserRequestModels.cs | 2 +-
.../Utilities/StrictEmailAddressAttribute.cs | 30 +++++++++++++++++++
....cs => StrictEmailAddressListAttribute.cs} | 6 ++--
7 files changed, 43 insertions(+), 23 deletions(-)
create mode 100644 src/Core/Utilities/StrictEmailAddressAttribute.cs
rename src/Core/Utilities/{EmailAddressListAttribute.cs => StrictEmailAddressListAttribute.cs} (83%)
diff --git a/src/Core/Models/Api/Public/Request/MemberCreateRequestModel.cs b/src/Core/Models/Api/Public/Request/MemberCreateRequestModel.cs
index a95d87deb9..58b4113bf2 100644
--- a/src/Core/Models/Api/Public/Request/MemberCreateRequestModel.cs
+++ b/src/Core/Models/Api/Public/Request/MemberCreateRequestModel.cs
@@ -2,36 +2,24 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Bit.Core.Models.Table;
+using Bit.Core.Utilities;
namespace Bit.Core.Models.Api.Public
{
- public class MemberCreateRequestModel : MemberUpdateRequestModel, IValidatableObject
+ public class MemberCreateRequestModel : MemberUpdateRequestModel
{
///
/// The member's email address.
///
/// jsmith@example.com
[Required]
- [EmailAddress]
+ [StringLength(256)]
+ [StrictEmailAddress]
public string Email { get; set; }
public override OrganizationUser ToOrganizationUser(OrganizationUser existingUser)
{
throw new NotImplementedException();
}
-
- public IEnumerable Validate(ValidationContext validationContext)
- {
- if (Email.Contains(" ") || Email.Contains("<"))
- {
- yield return new ValidationResult($"Email is not valid.",
- new string[] { nameof(Email) });
- }
- else if (Email.Length > 256)
- {
- yield return new ValidationResult($"Email is longer than 256 characters.",
- new string[] { nameof(Email) });
- }
- }
}
}
diff --git a/src/Core/Models/Api/Request/Accounts/EmailRequestModel.cs b/src/Core/Models/Api/Request/Accounts/EmailRequestModel.cs
index f29324bf92..b62a06b189 100644
--- a/src/Core/Models/Api/Request/Accounts/EmailRequestModel.cs
+++ b/src/Core/Models/Api/Request/Accounts/EmailRequestModel.cs
@@ -1,12 +1,13 @@
using System;
using System.ComponentModel.DataAnnotations;
+using Bit.Core.Utilities;
namespace Bit.Core.Models.Api
{
public class EmailRequestModel
{
[Required]
- [EmailAddress]
+ [StrictEmailAddress]
[StringLength(256)]
public string NewEmail { get; set; }
[Required]
diff --git a/src/Core/Models/Api/Request/Accounts/RegisterRequestModel.cs b/src/Core/Models/Api/Request/Accounts/RegisterRequestModel.cs
index 58a6db8485..6e7fda791f 100644
--- a/src/Core/Models/Api/Request/Accounts/RegisterRequestModel.cs
+++ b/src/Core/Models/Api/Request/Accounts/RegisterRequestModel.cs
@@ -4,6 +4,7 @@ using System.ComponentModel.DataAnnotations;
using Bit.Core.Enums;
using Bit.Core.Models.Business;
using Bit.Core.Models.Table;
+using Bit.Core.Utilities;
using Newtonsoft.Json;
namespace Bit.Core.Models.Api
@@ -13,7 +14,7 @@ namespace Bit.Core.Models.Api
[StringLength(50)]
public string Name { get; set; }
[Required]
- [EmailAddress]
+ [StrictEmailAddress]
[StringLength(256)]
public string Email { get; set; }
[Required]
diff --git a/src/Core/Models/Api/Request/Organizations/OrganizationUserRequestModels.cs b/src/Core/Models/Api/Request/Organizations/OrganizationUserRequestModels.cs
index e8d74da371..1bb368d9b6 100644
--- a/src/Core/Models/Api/Request/Organizations/OrganizationUserRequestModels.cs
+++ b/src/Core/Models/Api/Request/Organizations/OrganizationUserRequestModels.cs
@@ -12,7 +12,7 @@ namespace Bit.Core.Models.Api
public class OrganizationUserInviteRequestModel
{
[Required]
- [EmailAddressList]
+ [StrictEmailAddressList]
public IEnumerable Emails { get; set; }
[Required]
public Enums.OrganizationUserType? Type { get; set; }
diff --git a/src/Core/Models/Api/Request/Providers/ProviderUserRequestModels.cs b/src/Core/Models/Api/Request/Providers/ProviderUserRequestModels.cs
index f7afa59f61..7c87929628 100644
--- a/src/Core/Models/Api/Request/Providers/ProviderUserRequestModels.cs
+++ b/src/Core/Models/Api/Request/Providers/ProviderUserRequestModels.cs
@@ -11,7 +11,7 @@ namespace Bit.Core.Models.Api
public class ProviderUserInviteRequestModel
{
[Required]
- [EmailAddressList]
+ [StrictEmailAddressList]
public IEnumerable Emails { get; set; }
[Required]
public ProviderUserType? Type { get; set; }
diff --git a/src/Core/Utilities/StrictEmailAddressAttribute.cs b/src/Core/Utilities/StrictEmailAddressAttribute.cs
new file mode 100644
index 0000000000..870c45f305
--- /dev/null
+++ b/src/Core/Utilities/StrictEmailAddressAttribute.cs
@@ -0,0 +1,30 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.Text.RegularExpressions;
+
+namespace Bit.Core.Utilities
+{
+ public class StrictEmailAddressAttribute : ValidationAttribute
+ {
+ public StrictEmailAddressAttribute()
+ : base("The {0} field is not a valid e-mail address.")
+ {}
+
+ public override bool IsValid(object value)
+ {
+ var emailAddress = value?.ToString();
+ if (emailAddress == null)
+ {
+ return false;
+ }
+
+ var illegalChars = @"[\s<>()]";
+ if (Regex.IsMatch(emailAddress, illegalChars))
+ {
+ return false;
+ }
+
+ return new EmailAddressAttribute().IsValid(emailAddress);
+ }
+ }
+}
diff --git a/src/Core/Utilities/EmailAddressListAttribute.cs b/src/Core/Utilities/StrictEmailAddressListAttribute.cs
similarity index 83%
rename from src/Core/Utilities/EmailAddressListAttribute.cs
rename to src/Core/Utilities/StrictEmailAddressListAttribute.cs
index 62f2603020..16611d58e2 100644
--- a/src/Core/Utilities/EmailAddressListAttribute.cs
+++ b/src/Core/Utilities/StrictEmailAddressListAttribute.cs
@@ -4,11 +4,11 @@ using System.Linq;
namespace Bit.Core.Utilities
{
- public class EmailAddressListAttribute : ValidationAttribute
+ public class StrictEmailAddressListAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
- var emailAttribute = new EmailAddressAttribute();
+ var strictEmailAttribute = new StrictEmailAddressAttribute();
var emails = value as IList;
if (!emails?.Any() ?? true)
@@ -24,7 +24,7 @@ namespace Bit.Core.Utilities
for (var i = 0; i < emails.Count(); i++)
{
var email = emails.ElementAt(i);
- if (!emailAttribute.IsValid(email) || email.Contains(" ") || email.Contains("<"))
+ if (!strictEmailAttribute.IsValid(email))
{
return new ValidationResult($"Email #{i + 1} is not valid.");
}