ssafronova (ssafronova) wrote in changelog,
ssafronova
ssafronova
changelog

[livejournal] r18066: LJSUP-5494: Re-registered first validate...

Committer: ssafronova
LJSUP-5494: Re-registered first validated email cannot remove newer email addresses
U   trunk/cgi-bin/LJ/User.pm
U   trunk/htdocs/tools/emailmanage.bml
Modified: trunk/cgi-bin/LJ/User.pm
===================================================================
--- trunk/cgi-bin/LJ/User.pm	2011-01-20 09:02:03 UTC (rev 18065)
+++ trunk/cgi-bin/LJ/User.pm	2011-01-20 10:31:45 UTC (rev 18066)
@@ -2542,6 +2542,68 @@
     return sort keys %ret;
 }
 
+# read emails and calculate primitives:
+# date of last leaving
+# date of chain start
+# returns data of emails_info function with additional keys ('leaving', may be undef, and 'starting')
+# skips internal steps of chains
+# skips deleted emails
+# cleans out all chains, which are unusable for password restoring, i.e. 'leaving' is newer than 6 month old
+# must return array for printing on tools/emailmanage.bml
+sub emails_chained_info {
+    my $u = shift;
+
+    return $u->{'_emails_chained'} if defined $u->{'_emails_chained'};
+
+    my $emails = $u->emails_info;
+    my @email_addresses = $u->emails_unique;
+
+    my @chains;
+
+    # process all elements
+    foreach my $addr (@email_addresses) {
+        # find all information about this element
+        my ($starting, $leaving);
+        my $lc_addr = lc $addr;
+
+        my @relevant = grep { lc($_->{email}) eq $lc_addr } @$emails;
+            # already sorted by MySQL
+
+        my $step;
+        foreach $step (@relevant) {
+
+            next unless $step->{status} eq 'A'; # restoring can be done only by validated addressed
+
+            if ($step->{deleted}) {
+                undef $starting;
+                undef $leaving;
+                next;
+            }
+
+            if (defined $leaving and $step->{set} - $leaving > $LJ::EMAIL_FORGET_AGE) {
+                # forget old chain - because it is unusable for password restoring
+                undef $starting; # start new chain
+                undef $leaving;
+            }
+
+            # most early starting
+            $starting = $step->{set} unless defined $starting and $starting < $step->{set};
+
+            # most late leaving
+            $leaving = $step->{changed} unless defined $leaving and defined $step->{changed} and $step->{changed} < $leaving;
+        }
+
+        if ($starting and time - $leaving < $LJ::EMAIL_FORGET_AGE) {
+            push @chains, { email => $step->{email}, leaving => $leaving, starting => $starting }; # fix this chain
+                # we store address with upper case letters possibly,
+                # to make it more comfort for user when he/she reads address
+        }
+    }
+
+    $u->{'_emails_chained'} = \@chains;
+    return \@chains;
+}
+
 # returns time when the user has last stopped using the given email
 # (that is, switched their current address to a different one)
 # this ASSUMES that the address is not a current one, but that it was
@@ -2573,10 +2635,18 @@
 sub can_delete_email {
     my ($u, $addr) = @_;
 
-    my $lastchange = $u->email_lastchange($addr);
+    my $chains = $u->emails_chained_info;
 
-    return 0 unless defined $lastchange;
-    return $lastchange < time - 86400 * 180; # this is six months
+    # reformat as email => parameters hash
+    my %chains = map { lc($_->{email}) => $_ } @$chains;
+
+    my $current = lc $u->email_raw;
+    my $edge_age = $chains{$current}->{starting};
+
+    my $aim_value = $chains{lc $addr}->{starting};
+
+    return 0 unless defined $edge_age and $aim_value;
+    return $aim_value > $edge_age;
 }
 
 # delete the given email from user's history, disabling the user from sending
@@ -2636,12 +2706,22 @@
 sub can_reset_password_using_email {
     my ($u, $addr) = @_;
 
-    return 1 if lc($addr) eq lc($u->email_raw);
+    return 0 unless $LJ::DISABLED{'limit_password_reset'};
 
-    return 0 unless $LJ::DISABLED{'limit_password_reset'};
-    return
-        $u->is_email_validated($addr) && # validated
-        $u->email_lastchange($addr) > time - 86400 * 180; # six months
+    my $current = lc $u->email_raw;
+    return 1 if lc($addr) eq $current;
+
+    return 0 unless $u->is_email_validated($addr);
+
+    my $chains = $u->emails_chained_info;
+
+    # reformat as email => parameters hash
+    my %chains = map { lc($_->{email}) => $_ } @$chains;
+
+    my $aim_value = $chains{lc $addr}->{leaving};
+
+    return 0 unless defined $aim_value;
+    return time - $aim_value < $LJ::EMAIL_FORGET_AGE;
 }
 
 # returns date when the user has last changed their email

Modified: trunk/htdocs/tools/emailmanage.bml
===================================================================
--- trunk/htdocs/tools/emailmanage.bml	2011-01-20 09:02:03 UTC (rev 18065)
+++ trunk/htdocs/tools/emailmanage.bml	2011-01-20 10:31:45 UTC (rev 18066)
@@ -20,8 +20,8 @@
     return LJ::bad_input($ML{'error.invalidauth'})
         unless $u;
 
-    my $emails = $u->emails_info;
-    my @emails_unique = $u->emails_unique;
+    my $emails = $u->emails_chained_info;
+    my @emails_unique = map { lc $_->{email} } @$emails;
     my $email_current = $u->email_raw;
     my @delete_log;
 
@@ -77,17 +77,19 @@
     $ret .= "<table border='1' cellpadding='2' style='margin-bottom: 3px;'>\n";
 
     my $can_delete = 0;
-    foreach my $addr (@emails_unique) {
-        next if lc($addr) eq lc($email_current);
+    foreach my $addr (@$emails) {
+        next if lc($addr->{email}) eq lc($email_current);
 
-        next unless $u->is_email_validated($addr);
-        my $time = $dump_time->($u->email_lastchange($addr));
+        next unless $u->is_email_validated($addr->{email});
+        my $time = $dump_time->($addr->{leaving});
         my $can_delete_this = $u->can_delete_email($addr);
         $can_delete ||= $can_delete_this;
 
-        $ret .= "<tr><td>" . LJ::html_check({ 'type' => 'check', 'name' => "$addr",
+        my $starting = $GET{debug} ? "<td>$addr->{starting}</td>" : "";
+
+        $ret .= "<tr><td>" . LJ::html_check({ 'type' => 'check', 'name' => "$addr->{email}",
                                               'disabled' => !$can_delete_this } ) . "</td>";
-        $ret .= "<td>$addr</td><td>$time</td></tr>\n";
+        $ret .= "<td>$addr->{email}</td><td>$time</td>$starting</tr>\n";
     }
 
     $ret .= "</table>\n";

Tags: bml, livejournal, pm, ssafronova
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 0 comments