Committer: ailyin
LJSUP-11976 (refactor methods working with infohistory into classes of its own)U trunk/cgi-bin/LJ/Console/Command/ChangeCommunityAdmin.pm U trunk/cgi-bin/LJ/Console/Command/ChangeJournalType.pm U trunk/cgi-bin/LJ/Console/Command/Infohistory.pm U trunk/cgi-bin/LJ/Console/Command/ResetEmail.pm U trunk/cgi-bin/LJ/Console/Command/ResetPassword.pm U trunk/cgi-bin/LJ/Event/SecurityAttributeChanged.pm U trunk/cgi-bin/LJ/Poll.pm U trunk/cgi-bin/LJ/User/EmailStatus.pm A trunk/cgi-bin/LJ/User/InfoHistory.pm A trunk/cgi-bin/LJ/User/InfoHistoryRecord.pm U trunk/cgi-bin/LJ/User/Rename.pm U trunk/cgi-bin/LJ/User.pm U trunk/htdocs/changeemail.bml U trunk/htdocs/changepassword.bml U trunk/htdocs/manage/profile/index.bml U trunk/t/console-infohistory.t U trunk/t/console-reset.t
Modified: trunk/cgi-bin/LJ/Console/Command/ChangeCommunityAdmin.pm =================================================================== --- trunk/cgi-bin/LJ/Console/Command/ChangeCommunityAdmin.pm 2012-04-27 09:14:53 UTC (rev 21824) +++ trunk/cgi-bin/LJ/Console/Command/ChangeCommunityAdmin.pm 2012-04-27 11:15:14 UTC (rev 21825) @@ -46,8 +46,7 @@ LJ::set_rel($ucomm, $unew, 'A'); # so old maintainers can't regain access - my $dbh = LJ::get_db_writer(); - $dbh->do("DELETE FROM infohistory WHERE userid = ?", undef, $ucomm->id); + LJ::User::InfoHistory->clear($ucomm); # change password to blank and set email of community to new maintainer's email LJ::update_user($ucomm, { password => '', email => $unew->email_raw }); Modified: trunk/cgi-bin/LJ/Console/Command/ChangeJournalType.pm =================================================================== --- trunk/cgi-bin/LJ/Console/Command/ChangeJournalType.pm 2012-04-27 09:14:53 UTC (rev 21824) +++ trunk/cgi-bin/LJ/Console/Command/ChangeJournalType.pm 2012-04-27 11:15:14 UTC (rev 21825) @@ -141,17 +141,26 @@ $extra{password} = $ou->password; } - LJ::infohistory_add($u, 'password', Digest::MD5::md5_hex($u->password . 'change')) - if $extra{password} ne $u->password; + if ( $extra{password} ne $u->password ) { + LJ::User::InfoHistory->add( $u, + 'password', Digest::MD5::md5_hex( $u->password . 'change' ) ); + } # reset the email address $extra{email} = $ou->email_raw; $extra{status} = 'A'; + + # TODO: move this to LJ::User::InfoHistory or change it to adding a new + # entry; updating table with log data is not a good idea $dbh->do("UPDATE infohistory SET what='emailreset' WHERE userid=? AND what='email'", undef, $u->id) or $self->error("Error updating infohistory for emailreset: " . $dbh->errstr); - LJ::infohistory_add($u, 'emailreset', $u->email_raw, $u->email_status) - unless $ou->email_raw eq $u->email_raw; # record only if it changed + # record only if it changed + if ( $ou->email_raw ne $u->email_raw ) { + LJ::User::InfoHistory->add( $u, + 'emailreset', $u->email_raw, $u->email_status ); + } + # get the new journaltype $extra{journaltype} = $typemap->{$type}; Modified: trunk/cgi-bin/LJ/Console/Command/Infohistory.pm =================================================================== --- trunk/cgi-bin/LJ/Console/Command/Infohistory.pm 2012-04-27 09:14:53 UTC (rev 21824) +++ trunk/cgi-bin/LJ/Console/Command/Infohistory.pm 2012-04-27 11:15:14 UTC (rev 21825) @@ -30,20 +30,22 @@ return $self->error("Invalid user $user") unless $u; - my $dbh = LJ::get_db_reader(); - my $sth = $dbh->prepare("SELECT * FROM infohistory WHERE userid=?"); - $sth->execute($u->id); + my $infohistory = LJ::User::InfoHistory->get($u); return $self->error("No matches.") - unless $sth->rows; + unless @$infohistory; $self->info("Infohistory of user: $user"); - while (my $info = $sth->fetchrow_hashref) { - $info->{'oldvalue'} ||= '(none)'; - $self->info("Changed $info->{'what'} at $info->{'timechange'}."); - $self->info("Old value of $info->{'what'} was $info->{'oldvalue'}."); - $self->info("Other information recorded: $info->{'other'}") - if $info->{'other'}; + foreach my $record (@$infohistory) { + my $oldvalue = $record->oldvalue || '(none)'; + + $self->info( "Changed " . $record->what . + " at " . $record->timechange . "." ); + $self->info("Old value of " . $record->what . " was $oldvalue."); + + if ( my $other = $record->other ) { + $self->info("Other information recorded: $other"); + } } return 1; Modified: trunk/cgi-bin/LJ/Console/Command/ResetEmail.pm =================================================================== --- trunk/cgi-bin/LJ/Console/Command/ResetEmail.pm 2012-04-27 09:14:53 UTC (rev 21824) +++ trunk/cgi-bin/LJ/Console/Command/ResetEmail.pm 2012-04-27 11:15:14 UTC (rev 21825) @@ -33,8 +33,10 @@ my $aa = LJ::register_authaction($u->id, "validateemail", $newemail); - LJ::infohistory_add($u, 'emailreset', $u->email_raw, $u->email_status) - if $u->email_raw ne $newemail; + if ( $u->email_raw ne $newemail ) { + LJ::User::InfoHistory->add( $u, + 'emailreset', $u->email_raw, $u->email_status ); + } LJ::update_user($u, { email => $newemail, status => 'T' }) or return $self->error("Unable to set new email address for $username"); @@ -51,6 +53,8 @@ 'body' => $body, }) or $self->info("Confirmation email could not be sent."); + # TODO: move this to LJ::User::InfoHistory or change it to adding a new + # entry; updating table with log data is not a good idea my $dbh = LJ::get_db_writer(); $dbh->do("UPDATE infohistory SET what='emailreset' WHERE userid=? AND what='email'", undef, $u->id) or return $self->error("Database error: " . $dbh->errstr); Modified: trunk/cgi-bin/LJ/Console/Command/ResetPassword.pm =================================================================== --- trunk/cgi-bin/LJ/Console/Command/ResetPassword.pm 2012-04-27 09:14:53 UTC (rev 21824) +++ trunk/cgi-bin/LJ/Console/Command/ResetPassword.pm 2012-04-27 11:15:14 UTC (rev 21825) @@ -34,9 +34,7 @@ my $newpass = LJ::rand_chars(8); my $oldpass = Digest::MD5::md5_hex($u->password . "change"); - my $rval = LJ::infohistory_add($u, 'passwordreset', $oldpass); - return $self->error("Failed to insert old password into infohistory.") - unless $rval; + LJ::User::InfoHistory->add( $u, 'passwordreset', $oldpass ); LJ::update_user($u, { password => $newpass, }) or return $self->error("Failed to set new password for $username"); Modified: trunk/cgi-bin/LJ/Event/SecurityAttributeChanged.pm =================================================================== --- trunk/cgi-bin/LJ/Event/SecurityAttributeChanged.pm 2012-04-27 09:14:53 UTC (rev 21824) +++ trunk/cgi-bin/LJ/Event/SecurityAttributeChanged.pm 2012-04-27 11:15:14 UTC (rev 21825) @@ -58,35 +58,22 @@ # TODO: check is $u a user object? die "Missing credentials" unless $ip && $action && $old_username; - my $dbh = LJ::get_db_writer($u); - my $sth = $dbh->prepare( - "SELECT UNIX_TIMESTAMP(timechange) as utimechange, oldvalue". - " FROM infohistory". - " WHERE userid=? AND what='username'". - " ORDER BY utimechange DESC LIMIT 2"); - $sth->execute($userid); - my ($timechange, $oldvalue) = $sth->fetchrow_array; + my $infohistory = LJ::User::InfoHistory->get( $u, 'username' ); + my ($latest_record) = + reverse + sort { $a->timechange_unix <=> $b->timechange_unix } + @$infohistory; - # Check for errors die "This event (uid=$userid, what=username) was not found in logs" - unless $timechange; + unless $latest_record; + my $timechange = $latest_record->timechange_unix; + my $oldvalue = $latest_record->oldvalue; + die "Event (uid=$userid, what=username) was not found in logs". " has wrong old username: $oldvalue instead of $old_username" if $oldvalue ne $old_username; - my ($timechange2, $oldvalue2) = $sth->fetchrow_array; - die "Second record about this event was found in log" - if $timechange2 && $timechange2 == $timechange && ($oldvalue2 ne $oldvalue); - - # Remember ip address - $dbh->do( - "UPDATE infohistory". - " SET other='ip=$ip'". - " WHERE userid=$userid". - " AND what='username'". - " AND UNIX_TIMESTAMP(timechange)=$timechange"); - return $timechange; }; @@ -201,20 +188,19 @@ my ($u, $timechange_stamp) = @_; my $userid = $u->{userid}; - my $dbh = LJ::get_db_reader($u); - my $sth = $dbh->prepare( - "SELECT oldvalue, other". - " FROM infohistory". - " WHERE userid=? AND what='username' AND UNIX_TIMESTAMP(timechange)=?"); - $sth->execute($userid, $timechange_stamp); - my ($old_name, $other) = $sth->fetchrow_array; + my $infohistory = LJ::InfoHistory->get( $u, 'username' ); + my ($infohistory_record) = + grep { $_->timechange_unix == $timechange_stamp } + @$infohistory; - # Check for errors - unless ($old_name) { + unless ($infohistory_record) { croak "This event (uid=$userid, what=username) was not found in logs"; return undef; } + my $old_name = $infohistory_record->oldvalue; + my $other = $infohistory_record->other; + # Convert $timechange from GMT to local for user my $offset = 0; LJ::get_timezone($u, \$offset); Modified: trunk/cgi-bin/LJ/Poll.pm =================================================================== --- trunk/cgi-bin/LJ/Poll.pm 2012-04-27 09:14:53 UTC (rev 21824) +++ trunk/cgi-bin/LJ/Poll.pm 2012-04-27 11:15:14 UTC (rev 21825) @@ -2127,20 +2127,10 @@ } if (@$uids) { - my $remote_email = $remote->email_raw; my $us = LJ::load_userids(@$uids); # Get all emails for the user submitting the poll - my $dbr = LJ::get_db_reader(); - my $sth = $dbr->prepare("SELECT oldvalue FROM infohistory " . - "WHERE userid=? AND what='email' " . - "ORDER BY timechange"); - $sth->execute($remote->{'userid'}); - my @emails; - push @emails, $remote_email; - while (my $em = $sth->fetchrow_array) { - push @emails, $em; - } + my @emails = map { $_->{'email'} } @{ $remote->emails_info }; foreach my $u (values %$us) { next unless $u; Modified: trunk/cgi-bin/LJ/User/EmailStatus.pm =================================================================== --- trunk/cgi-bin/LJ/User/EmailStatus.pm 2012-04-27 09:14:53 UTC (rev 21824) +++ trunk/cgi-bin/LJ/User/EmailStatus.pm 2012-04-27 11:15:14 UTC (rev 21825) @@ -142,7 +142,8 @@ my $new_status = $is_disabled ? 'T' : 'A'; LJ::update_user($user, { 'status' => $new_status } ); - LJ::infohistory_add($user->userid, 'email_status', $old_status, $user->email_raw); + LJ::User::InfoHistory->add( $user, + 'email_status', $old_status, $user->email_raw ); } } Added: trunk/cgi-bin/LJ/User/InfoHistory.pm =================================================================== --- trunk/cgi-bin/LJ/User/InfoHistory.pm (rev 0) +++ trunk/cgi-bin/LJ/User/InfoHistory.pm 2012-04-27 11:15:14 UTC (rev 21825) @@ -0,0 +1,66 @@ +package LJ::User::InfoHistory; +use strict; +use warnings; + +use LJ::User::InfoHistoryRecord; + +sub add { + my ( $class, $u, $what, $oldvalue, $other ) = @_; + + my $dbh = LJ::get_db_writer(); + local $dbh->{'RaiseError'} = 1; + + $dbh->do( + 'INSERT INTO infohistory ' . + 'SET userid=?, what=?, timechange=NOW(), oldvalue=?, other=?', + undef, + $u->userid, $what, $oldvalue, $other, + ); + + $LJ::REQ_GLOBAL{'infohistory_cache'} ||= {}; + delete $LJ::REQ_GLOBAL{'infohistory_cache'}->{ $u->userid }; + +} + +sub get { + my ( $class, $u, $what ) = @_; + + $LJ::REQ_GLOBAL{'infohistory_cache'} ||= {}; + unless ( exists $LJ::REQ_GLOBAL{'infohistory_cache'}->{ $u->userid } ) { + my $dbr = LJ::get_db_reader(); + local $dbr->{'RaiseError'} = 1; + + my $rows = $dbr->selectall_arrayref( + 'SELECT * FROM infohistory WHERE userid=? ORDER BY timechange', + { 'Slice' => {} }, + $u->userid, + ); + + $LJ::REQ_GLOBAL{'infohistory_cache'}->{ $u->userid } = + [ map { LJ::User::InfoHistoryRecord->new($_) } @$rows ]; + } + + my $records = $LJ::REQ_GLOBAL{'infohistory_cache'}->{ $u->userid }; + return $records unless $what; + + if ( ref $what eq 'ARRAY' ) { + my %acceptable_what = map { $_ => 1 } @$what; + return [ grep { $acceptable_what{ $_->what } } @$records; + } else { + return [ grep { $_->what eq $what } @$records ]; + } +} + +sub clear { + my ( $class, $u ) = @_; + + my $dbh = LJ::get_db_writer(); + local $dbh->{'RaiseError'} = 1; + + $dbh->do( 'DELETE FROM infohistory WHERE userid=?', undef, $u->userid ); + + $LJ::REQ_GLOBAL{'infohistory_cache'} ||= {}; + $LJ::REQ_GLOBAL{'infohistory_cache'}->{ $u->userid } = []; +} + +1; Added: trunk/cgi-bin/LJ/User/InfoHistoryRecord.pm =================================================================== --- trunk/cgi-bin/LJ/User/InfoHistoryRecord.pm (rev 0) +++ trunk/cgi-bin/LJ/User/InfoHistoryRecord.pm 2012-04-27 11:15:14 UTC (rev 21825) @@ -0,0 +1,23 @@ +package LJ::User::InfoHistoryRecord; +use strict; +use warnings; + +use base qw( Class::Accessor ); +__PACKAGE__->mk_ro_accessors( qw( userid what timechange oldvalue other ) ); + +sub new { + my ( $class, $row ) = @_; + return bless { %$row }, $class; +} + +sub user { + my ($self) = @_; + return LJ::load_userid( $self->userid ); +} + +sub timechange_unix { + my ($self) = @_; + return LJ::TimeUtil->mysqldate_to_time( $self->timechange ); +} + +1; Modified: trunk/cgi-bin/LJ/User/Rename.pm =================================================================== --- trunk/cgi-bin/LJ/User/Rename.pm 2012-04-27 09:14:53 UTC (rev 21824) +++ trunk/cgi-bin/LJ/User/Rename.pm 2012-04-27 11:15:14 UTC (rev 21825) @@ -165,8 +165,11 @@ $dbh->do("DELETE FROM expunged_users WHERE user IN (?, ?)", undef, $from, $to); - LJ::infohistory_add($u, 'username', $from); + my $ip = $opts->{'ip'}; + $ip ||= LJ::is_web_context() ? LJ::Request->remote_ip() : '127.0.0.1'; + LJ::User::InfoHistory->add( $u, 'username', $from, "ip=$ip" ); + # tell all web machines to clear their caches for this userid/name mapping LJ::procnotify_add("rename_user", { 'userid' => $u->{'userid'}, 'user' => $u->{'user'} }); @@ -194,7 +197,7 @@ LJ::Event::SecurityAttributeChanged->new($u , { action => 'account_renamed', old_username => $from, - ip => ($opts->{ip} || (LJ::is_web_context() ? LJ::Request->remote_ip() : '127.0.0.1')), + ip => $ip, datetime => sprintf("%02d:%02d %02d/%02d/%04d", @date[2,1], $date[3], $date[4]+1, $date[5]+1900), })->fire; } Modified: trunk/cgi-bin/LJ/User.pm =================================================================== --- trunk/cgi-bin/LJ/User.pm 2012-04-27 09:14:53 UTC (rev 21824) +++ trunk/cgi-bin/LJ/User.pm 2012-04-27 11:15:14 UTC (rev 21825) @@ -10,44 +10,50 @@ # so the queries can be tagged for use by the star replication # daemon. +package LJ::User; use strict; no warnings 'uninitialized'; -package LJ::User; -use Carp; use lib "$ENV{LJHOME}/cgi-bin"; -use List::Util (); -use LJ::Request; + +use Carp; +use HTTP::Date qw( str2time ); +use List::Util qw(); +use URI qw(); + use LJ::Constants; +use LJ::JSON; +use LJ::FileStore; use LJ::MemCache; +use LJ::RateLimit qw(); +use LJ::RelationService; +use LJ::Request; use LJ::Session; -use LJ::RateLimit qw//; -use URI qw//; -use LJ::JSON; -use HTTP::Date qw(str2time); use LJ::TimeUtil; +use LJ::User::InfoHistory; use LJ::User::PropStorage; -use LJ::FileStore; -use LJ::RelationService; +# TODO: get rid of Class::Autouse, maybe? it's pretty useless +# in web context and leads to some nasty bugs otherwise, so probably +# the benefit is not worth it use Class::Autouse qw( - URI - LJ::Subscription - LJ::SMS - LJ::SMS::Message - LJ::Identity - LJ::Auth - LJ::Jabber::Presence - LJ::S2 - IO::Socket::INET - Time::Local - LJ::M::FriendsOf - LJ::BetaFeatures - LJ::S2Theme - LJ::Subscription - LJ::Subscription::GroupSet - ); + IO::Socket::INET + Time::Local + LJ::Auth + LJ::BetaFeatures + LJ::Identity + LJ::Jabber::Presence + LJ::M::FriendsOf + LJ::Subscription + LJ::S2 + LJ::S2Theme + LJ::SMS + LJ::SMS::Message + LJ::Subscription + LJ::Subscription::GroupSet +); + # class method to create a new account. sub create { my ($class, %opts) = @_; @@ -2335,16 +2341,11 @@ sub last_password_change_time { my ($u) = @_; - my $dbr = LJ::get_db_reader(); - my ($time) = $dbr->selectrow_array( - 'SELECT UNIX_TIMESTAMP(MAX(timechange)) FROM infohistory ' . - 'WHERE userid=? AND what="password"', - undef, - $u->userid, - ); + my $infohistory = LJ::User::InfoHistory->get( $u, 'password' ); + my @password_change_timestamps = map { $_->timechange_unix } @$infohistory; - $time ||= 0; - return $time; + return 0 unless @password_change_timestamps; + return List::Util::max( @password_change_timestamps ); } # THIS IS DEPRECATED DO NOT USE @@ -2466,20 +2467,6 @@ return 1; } -# this is DEPRECATED in favor of can_reset_password_using_email -sub can_receive_password { - my ($u, $email) = @_; - - return 0 unless $u && $email; - return 1 if lc($email) eq lc($u->email_raw); - - my $dbh = LJ::get_db_reader(); - return $dbh->selectrow_array("SELECT COUNT(*) FROM infohistory ". - "WHERE userid=? AND what='email' ". - "AND oldvalue=? AND other='A'", - undef, $u->id, $email); -} - # my $u = LJ::want_user(12); # my $data = $u->get_email_data('test@test.ru'); # print $data->{'email_state'}; # email status if test@test.ru is the @@ -2523,23 +2510,31 @@ my @ret; - my $dbr = LJ::get_db_reader(); - my $infohistory_rows = $dbr->selectall_arrayref( - 'SELECT what, UNIX_TIMESTAMP(timechange) AS timechange, '. - 'oldvalue, other FROM infohistory WHERE userid=? AND '. - 'what IN ("email", "emaildeleted") ORDER BY timechange', - { Slice => {} }, $u->id - ); - my @infohistory_rows = @$infohistory_rows; + my $infohistory = + LJ::User::InfoHistory->get( $u, [ 'email', 'emaildeleted' ] ); - # this actually finds the greatest timechange in rows before $rownum; + my $infohistory_records = + [ sort { $a->timechange_unix <=> $b->timechange_unix } @$infohistory ]; + + # my $dbr = LJ::get_db_reader(); + # my $infohistory_rows = $dbr->selectall_arrayref( + # 'SELECT what, UNIX_TIMESTAMP(timechange) AS timechange, '. + # 'oldvalue, other FROM infohistory WHERE userid=? AND '. + # 'what IN ("email", "emaildeleted") ORDER BY timechange', + # { Slice => {} }, $u->id + # ); + # my @infohistory_rows = @$infohistory_rows; + + # this actually finds the greatest timechange in rows before $recordnum; # if it fails to find it, it returns $u->timecreate my $find_timeset = sub { - my ($rownum) = @_; + my ($recordnum) = @_; - for (my $rownum2 = $rownum-1; $rownum2 >= 0; $rownum2--) { - my $row2 = $infohistory_rows->[$rownum2]; - return $row2->{'timechange'} if ($row2->{'what'} eq 'email'); + for ( my $recordnum2 = $recordnum - 1; + $recordnum2 >= 0; $recordnum2-- ) + { + my $record2 = $infohistory_records->[$recordnum2]; + return $record2->timechange_unix if $record2->what eq 'email'; } # in case we found nothing, the address was set when the account @@ -2547,23 +2542,18 @@ return $u->timecreate; }; - foreach my $rownum (0..$#infohistory_rows) { - my $row = $infohistory_rows->[$rownum]; - if ($row->{'what'} eq 'email') { + foreach my $recordnum ( 0 .. $#$infohistory_records ) { + my $record = $infohistory_records->[$recordnum]; + if ( $record->what eq 'email' ) { # new email has been added to the list, but now, we're going to # record the old address - - my $email = { email => $row->{'oldvalue'} }; - $email->{'changed'} = $row->{'timechange'}; - $email->{'status'} = $row->{'other'}; - - # in case we found nothing, the address was set when the account - # was registered - - $email->{'set'} = $find_timeset->($rownum); - - push @ret, $email; - } elsif ($row->{'what'} eq 'emaildeleted') { + push @ret, { + 'email' => $record->oldvalue, + 'changed' => $record->timechange_unix, + 'status' => $record->other, + 'set' => $find_timeset->($recordnum), + }; + } elsif ( $record->what eq 'emaildeleted' ) { # there may be two cases here: 1) it was something like an admin # deletion or 2) it was deletion through /tools/emailmanage.bml, # which previously did 'UPDATE infohistory SET what="emaildelete"' @@ -2571,57 +2561,59 @@ # /tools/emailmanage.bml has since been changed to record that # change as a new entry, which returns us to the first case - unless ($row->{'other'} =~ /;/) { + unless ( $record->other =~ /;/ ) { # first case: find all other occurences of that email # and mark them with the date of deletion foreach my $email (@ret) { - next unless $email->{'email'} eq $row->{'oldvalue'}; - next unless $email->{'set'} <= $row->{'timechange'}; + next unless $email->{'email'} eq $record->oldvalue; + next unless $email->{'set'} <= $record->timechange_unix; - $email->{'deleted'} = $row->{'timechange'} + $email->{'deleted'} = $record->timechange_unix unless $email->{'deleted'}; } } else { # second case: parse the timestamp, create an email hashref, - # find the row with the next address to set "set", and + # find the record with the next address to set "set", and # finally, mark it as deleted. ugh. - my ($status, $time) = split /;/, $row->{'other'}; + my ( $status, $time ) = split /;/, $record->other; # there is no joke here. in infohistory, time is stored as # MySQL DATETIME. emailmanage.bml used to just append it to # previous status, so now, we need to parse. $time = str2time($time); - my $email = { email => $row->{'oldvalue'} }; - $email->{'changed'} = $time; - $email->{'status'} = $status; - $email->{'deleted'} = $row->{'timechange'}; + # we need to find the first record which has timestamp + # greater or equal to $time so that we can call $find_timeset + my $nextrecord = 0; + foreach my $recordnum2 ( 0 .. $#$infohistory_records ) { + my $record2 = $infohistory_records->[$recordnum2]; + next unless $record2->what eq 'email'; + next if $record2->timechange_unix < $time; - # now, we need to find the first row which has timestamp more - # or equal to $time so that we can call $find_timeset - my $nextrow = 0; - foreach my $rownum2 (0..$#infohistory_rows) { - my $row2 = $infohistory_rows->[$rownum2]; - next unless $row2->{'what'} eq 'email'; - next if $row2->{'timechange'} < $time; - - $nextrow = $rownum2; + $nextrecord = $recordnum2; last; } - $email->{'set'} = $find_timeset->($nextrow); - push @ret, $email; + push @ret, { + 'email' => $record->oldvalue, + 'changed' => $time, + 'status' => $status, + 'deleted' => $record->timechange_unix, + 'set' => $find_timeset->($nextrecord), + }; } } } # finally, the current address - my $email = { email => $u->email_raw, current => 1 }; - $email->{'status'} = $u->email_status; - $email->{'set'} = $find_timeset->($#infohistory_rows + 1); - push @ret, $email; + push @ret, { + 'email' => $u->email_raw, + 'current' => 1, + 'status' => $u->email_status, + 'set' => $find_timeset->( $#$infohistory_records + 1 ), + }; $u->{'_emails'} = \@ret; return \@ret; @@ -2762,15 +2754,9 @@ return unless $u->can_delete_email($addr); - my $dbh = LJ::get_db_writer(); - $dbh->do( - 'INSERT INTO infohistory SET '. - 'userid=?, what="emaildeleted", timechange=NOW(), '. - 'oldvalue=?', undef, $u->id, $addr - ); + LJ::User::InfoHistory->add( $u, 'emaildeleted', $addr ); # update cache now - my $emails = $u->emails_info; foreach my $email (@$emails) { next if $email->{'deleted'}; @@ -6046,7 +6032,7 @@ LJ::memcache_kill($u, "userid"); - LJ::infohistory_add($u, 'identity', $from); + LJ::User::InfoHistory->add( $u, 'identity', $from ); return 1; } @@ -7694,29 +7680,6 @@ } # <LJFUNC> -# name: LJ::infohistory_add -# des: Add a line of text to the [[dbtable[infohistory]] table for an account. -# args: uuid, what, value, other? -# des-uuid: User id or user object to insert infohistory for. -# des-what: What type of history is being inserted (15 chars max). -# des-value: Value for the item (255 chars max). -# des-other: Optional. Extra information / notes (30 chars max). -# returns: 1 on success, 0 on error. -# </LJFUNC> -sub infohistory_add { - my ($uuid, $what, $value, $other) = @_; - $uuid = LJ::want_userid($uuid); - return unless $uuid && $what && $value; - - # get writer and insert - my $dbh = LJ::get_db_writer(); - my $gmt_now = LJ::TimeUtil->mysql_time(time(), 1); - $dbh->do("INSERT INTO infohistory (userid, what, timechange, oldvalue, other) VALUES (?, ?, ?, ?, ?)", - undef, $uuid, $what, $gmt_now, $value, $other); - return $dbh->err ? 0 : 1; -} - -# <LJFUNC> # name: LJ::get_shared_journals # des: Gets an array of shared journals a user has access to. # returns: An array of shared journals. Modified: trunk/htdocs/changeemail.bml =================================================================== --- trunk/htdocs/changeemail.bml 2012-04-27 09:14:53 UTC (rev 21824) +++ trunk/htdocs/changeemail.bml 2012-04-27 11:15:14 UTC (rev 21825) @@ -125,7 +125,8 @@ LJ::statushistory_add($u->{userid}, $u->{userid}, 'email_changed', $loginfo); - LJ::infohistory_add($u, 'email', $old_email, $u->{status}); + LJ::User::InfoHistory->add( $u, + 'email', $old_email, $u->email_status ); $u->log_event('email_change', { remote => $remote, new => $POST{'email'} }); Modified: trunk/htdocs/changepassword.bml =================================================================== --- trunk/htdocs/changepassword.bml 2012-04-27 09:14:53 UTC (rev 21824) +++ trunk/htdocs/changepassword.bml 2012-04-27 11:15:14 UTC (rev 21825) @@ -44,7 +44,7 @@ # verify the email can still receive passwords return LJ::bad_input(BML::ml('.error.emailchanged', { 'aopts' => "href='$LJ::SITEROOT/lostinfo.bml'"})) - unless $authu->can_receive_password($aa->{arg1}); + unless $authu->can_reset_password_using_email( $aa->{'arg1'} ); } my $update_form = sub { @@ -178,7 +178,7 @@ ## make note of changed password my $dbh = LJ::get_db_writer(); my $oldval = Digest::MD5::md5_hex($u->password . "change"); - LJ::infohistory_add($u, 'password', $oldval); + LJ::User::InfoHistory->add( $u, 'password', $oldval ); $u->log_event('password_change', { remote => $remote }); Modified: trunk/htdocs/manage/profile/index.bml =================================================================== --- trunk/htdocs/manage/profile/index.bml 2012-04-27 09:14:53 UTC (rev 21824) +++ trunk/htdocs/manage/profile/index.bml 2012-04-27 11:15:14 UTC (rev 21825) @@ -854,7 +854,8 @@ my $email_changed = (($u->email_raw ne $POST{'email'}) && !$LJ::EMAIL_CHANGE_REQUIRES_PASSWORD); if ($email_changed) { # record old email address; - LJ::infohistory_add($u, 'email', $u->email_raw, $u->{status}); + LJ::User::InfoHistory->add( $u, + 'email', $u->email_raw, $u->email_status ); $u->log_event('email_change', { remote => $remote, new => $POST{'email'} }); Modified: trunk/t/console-infohistory.t =================================================================== --- trunk/t/console-infohistory.t 2012-04-27 09:14:53 UTC (rev 21824) +++ trunk/t/console-infohistory.t 2012-04-27 11:15:14 UTC (rev 21825) @@ -24,7 +24,7 @@ "error: No matches."); # put something in there. -LJ::infohistory_add($u2, 'email', $u2->email_raw, 'T'); +LJ::User::InfoHistory->add( $u2, 'email', $u2->email_raw, 'T' ); my $response = $run->("infohistory " . $u2->user); like($response, qr/Changed email at \d{4}-\d{2}-\d{2}/, "Date recorded correctly."); Modified: trunk/t/console-reset.t =================================================================== --- trunk/t/console-reset.t 2012-04-27 09:14:53 UTC (rev 21824) +++ trunk/t/console-reset.t 2012-04-27 11:15:14 UTC (rev 21825) @@ -31,8 +31,8 @@ is($u2->email_status, "T", "Email status set correctly."); my $dbh = LJ::get_db_reader(); -my $rv = $dbh->do("SELECT * FROM infohistory WHERE userid=? AND what='email'", undef, $u2->id); -ok($rv < 1, "Addresses wiped from infohistory."); +my $infohistory = LJ::User::InfoHistory->get( $u2, 'email' ); +ok( @$infohistory < 1, "Addresses wiped from infohistory." ); $u->revoke_priv("reset_email");