diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index e5e20ee1d..9eca8858e 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -18,6 +18,7 @@ - fixed #11995: recurring calendar entries in trash - fixed #11986: Finance::Quote can give invalid dates to StockData asset - fixed #12001: Shelf product import mangles price + - fixed #11945: Slow SQL access for duplicate e-mail address lookups 7.10.6 - fixed #11974: Toolbar icons unclickable in Webkit using HTML5 diff --git a/docs/upgrades/upgrade_7.10.6-7.10.7.pl b/docs/upgrades/upgrade_7.10.6-7.10.7.pl index 6ffdb7198..edf4dabcf 100644 --- a/docs/upgrades/upgrade_7.10.6-7.10.7.pl +++ b/docs/upgrades/upgrade_7.10.6-7.10.7.pl @@ -31,6 +31,7 @@ my $quiet; # this line required my $session = start(); # this line required # upgrade functions go here +addEmailIndexToProfile( $session ); finish($session); # this line required @@ -44,6 +45,15 @@ finish($session); # this line required # print "DONE!\n" unless $quiet; #} +#---------------------------------------------------------------------------- +# Add an index to the userProfileData table for email lookups +sub addEmailIndexToProfile { + my $session = shift; + print "\tAdding index to email column on userProfileData table... " unless $quiet; + # and here's our code + $session->db->write( "ALTER TABLE userProfileData ADD INDEX email ( email )" ); + print "DONE!\n" unless $quiet; +} # -------------- DO NOT EDIT BELOW THIS LINE -------------------------------- diff --git a/lib/WebGUI/User.pm b/lib/WebGUI/User.pm index aed33918c..1447dfab8 100644 --- a/lib/WebGUI/User.pm +++ b/lib/WebGUI/User.pm @@ -27,6 +27,7 @@ use WebGUI::Shop::Credit; use JSON; use WebGUI::Exception; use WebGUI::ProfileField; +use List::MoreUtils qw( any ); use Scalar::Util qw( weaken ); =head1 NAME @@ -896,6 +897,25 @@ sub isAdmin { #------------------------------------------------------------------- +=head2 isDuplicateEmail( email ) + +Returns true if the email passed is also being used by any other user + +=cut + +sub isDuplicateEmail { + my ( $self, $email ) = @_; + + my @userIds = $self->session->db->quickArray( + "SELECT userId FROM userProfileData WHERE email = ?", + [ $email ], + ); + + return any { $_ ne $self->userId } @userIds; +} + +#------------------------------------------------------------------- + =head2 isEnabled () Returns 1 if the user is enabled. @@ -1552,7 +1572,7 @@ sub validateProfileDataFromForm { push(@{$errorFields},$fieldId); } #Duplicate emails throw warnings - elsif($fieldId eq "email" && $field->isDuplicate($fieldValue,$self->userId)) { + elsif($fieldId eq "email" && $self->isDuplicateEmail($fieldValue)) { $errorCat = $field->get("profileCategoryId") unless (defined $errorCat); push (@{$warnings},$i18n->get(1072)); push(@{$warnFields},$fieldId); diff --git a/t/User.t b/t/User.t index 398069eaa..bca703dbf 100644 --- a/t/User.t +++ b/t/User.t @@ -22,7 +22,7 @@ use WebGUI::User; use WebGUI::ProfileField; use WebGUI::Shop::AddressBook; -use Test::More tests => 226; # increment this value for each test you create +use Test::More tests => 233; # increment this value for each test you create use Test::Deep; use Data::Dumper; @@ -1048,6 +1048,39 @@ is($inmate->getInboxSmsNotificationAddress, '37927@textme.com', '... returns cel $inmate->profileField('cellPhone', '(555)-555.5555'); is($inmate->getInboxSmsNotificationAddress, '5555555555@textme.com', '... strips non digits from cellphone'); +################################################################ +# +# isDuplicateEmail +# +################################################################ + +$newFish->profileField( 'email' => 'tommy@shawshank.com' ); +ok( $inmate->isDuplicateEmail( 'tommy@shawshank.com' ), 'isDuplicateEmail triggers for duplicate email' ); +$inmate->profileField( 'email' => 'andy@shawshank.com' ); +ok( !$inmate->isDuplicateEmail( 'andy@shawshank.com' ), "isDuplicateEmail doesn't trigger for our email" ); + +################################################################ +# +# validateProfileDataFromForm +# +################################################################ + +my $profileData = { + email => 'tommy@shawshank.com', + language => 'SmoothBankerTalk', +}; +$session->request->setup_body( $profileData ); + +# Also check for firstName, which is not in request +my @fields = map { WebGUI::ProfileField->new( $session, $_ ); } ( keys %$profileData, "firstName" ); +my $reply = $inmate->validateProfileDataFromForm( \@fields ); + +cmp_deeply( $reply->{errorFields}, [ "language" ], "language isn't found, errors" ); +is( scalar( @{$reply->{errors}} ), 1, "error messages contains one message" ); +cmp_deeply( $reply->{warningFields}, [ "email" ], "email is duplicate, warns" ); +is( scalar( @{$reply->{warnings}} ), 1, "warnings messages contains one message" ); +cmp_deeply( $reply->{profile}, $profileData, "profile data makes it through" ); + ################################################################ # # delete