ljr/ljcom/bin/renameuser.pl

160 lines
4.2 KiB
Perl
Executable File

#!/usr/bin/perl
#
# <LJDEP>
# lib: cgi-bin/ljlib.pl
# </LJDEP>
use strict;
use Getopt::Long;
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
sub usage {
die "Usage: [--swap --force] <from_user> <to_user>\n";
}
my %args = ( swap => 0, force => 0 );
usage() unless
GetOptions('swap' => \$args{swap},
'force' => \$args{force},
);
my $error;
my $from = shift @ARGV;
my $to = shift @ARGV;
usage() unless $from =~ /^\w{1,15}$/ && $to =~ /^\w{1,15}$/;
my $dbh = LJ::get_db_writer();
unless ($args{swap}) {
if (rename_user($from, $to)) {
print "Success. Renamed $from -> $to.\n";
} else {
print "Failed: $error\n";
}
exit;
}
### check that emails/passwords match, and that at least one is verified
my $qfrom = $dbh->quote(lc($from));
my $qto = $dbh->quote(lc($to));
unless ($args{force}) {
my $sth = $dbh->prepare("SELECT user, email, password, status FROM user WHERE user IN ($qfrom, $qto)");
$sth->execute;
{
my @acct;
while (my $l = $sth->fetchrow_hashref) {
push @acct, $l;
}
unless (@acct == 2) {
print "Both accounts aren't valid.\n";
exit 1;
}
unless (lc($acct[0]->{'email'}) eq lc($acct[1]->{'email'})) {
print "Email addresses don't match.\n";
print " $acct[0]->{'email'}\n";
print " $acct[1]->{'email'}\n";
exit 1;
}
unless ($acct[0]->{'password'} eq $acct[1]->{'password'}) {
print "Passwords don't match.\n";
exit 1;
}
unless ($acct[0]->{'status'} eq "A" || $acct[1]->{'status'} eq "A") {
print "At least one account isn't verified.\n";
exit 1;
}
}
}
my $swapnum = 0;
print "Swapping 1/3...\n";
until ($swapnum == 10 || rename_user($from, "lj_swap_$swapnum")) {
$swapnum++;
}
if ($swapnum == 10) {
print "Couldn't find a swap position?\n";
exit 1;
}
print "Swapping 2/3...\n";
unless (rename_user($to, $from)) {
print "Swap failed in the middle, from $to -> $from failed.\n";
exit 1;
}
print "Swapping 3/3...\n";
unless (rename_user("lj_swap_$swapnum", $to)) {
print "Swap failed in the middle, from lj_swap_$swapnum -> $to failed.\n";
exit 1;
}
# check for circular 'renamedto' references
{
# if the fromuser had redirection on, make sure it points to the new $to user
my $fromu = LJ::load_user($from, 'force');
LJ::load_user_props($fromu, 'renamedto');
if ($fromu->{renamedto} && $fromu->{renamedto} ne $to) {
print "Setting redirection: $from => $to\n";
unless (LJ::set_userprop($fromu, 'renamedto' => $to)) {
print "Error setting 'renamedto' userprop for $from\n";
exit 1;
}
}
# if the $to user had redirection, they shouldn't anymore
my $tou = LJ::load_user($to, 'force');
LJ::load_user_props($tou, 'renamedto');
if ($tou->{renamedto}) {
print "Removing redirection for user: $to\n";
unless (LJ::set_userprop($tou, 'renamedto' => undef)) {
print "Error setting 'renamedto' userprop for $to\n";
exit 1;
}
}
}
print "Swapped.\n";
exit 0;
sub rename_user
{
my $from = shift;
my $to = shift;
my $qfrom = $dbh->quote(LJ::canonical_username($from));
my $qto = $dbh->quote(LJ::canonical_username($to));
print "Renaming $from -> $to\n";
my $u = LJ::load_user($from, 'force');
unless ($u) {
$error = "Invalid source user: $from";
return 0;
}
foreach my $table (qw(user useridmap overrides style))
{
$dbh->do("UPDATE $table SET user=$qto WHERE user=$qfrom");
if ($dbh->err) {
$error = $dbh->errstr;
return 0;
}
}
# from user is now invalidated
LJ::memcache_kill($u->{userid}, "userid");
LJ::MemCache::delete("uidof:$from");
LJ::MemCache::delete("uidof:$to");
LJ::procnotify_add("rename_user", { 'user' => $u->{'user'},
'userid' => $u->{'userid'} });
$dbh->do("INSERT INTO renames (renid, token, payid, userid, fromuser, touser, rendate) ".
"VALUES (NULL,'[manual]',0,$u->{userid},$qfrom,$qto,NOW())");
return 1;
}