head	1.3;
access;
symbols;
locks; strict;
comment	@# @;


1.3
date	2001.08.09.20.56.50;	author kmaples;	state Exp;
branches;
next	1.2;

1.2
date	2001.08.03.02.53.53;	author kmaples;	state Exp;
branches;
next	1.1;

1.1
date	2001.07.19.00.19.14;	author kmaples;	state Exp;
branches;
next	;


desc
@@


1.3
log
@Added line to update the password/encrypted password fields with bogus data.
@
text
@#!/usr/bin/perl -w
# $Id: consolidate_iz_users.pl,v 1.2 2001/08/03 02:53:53 kmaples Exp $ 
use strict;
use DBI;
use Getopt::Long;

BEGIN
{
    unshift(@@INC, "$ENV{SANDBOX}/scripts");
}
use HelmDB;

# Command-line vars:
my $datafile         = '';
my $default_username = '';
my $minimum_role     = '';


my @@skipped_lines       = ();
my @@usernames_to_delete = ();
my @@missing_scast_users = ();
my @@missing_iz_users    = ();
my @@created_iz_accts    = ();
my %scast_user;

# $scast_user{username} = (
#   id            => $userid,
#   old           => [email1, email2 ... emailN] 


my %helm_roles = (
    'admin'     => 127,
    'developer' => 96, 
    'observer'  => 0, 
);

check_errors();

GetOptions(
    'datafile=s'         => \$datafile,
    'default_username=s' => \$default_username,
    'minimum_role=s'     => \$minimum_role, 
);

# Set a default name for the issues bitbucket.
$default_username ||= 'defunct_userissues'; 

# Get db connections to helm and IZ:
my $IZDBC   = HelmDB::connect($ENV{IZ_DATABASE_NAME}, $ENV{DATABASE_USER}, $ENV{DATABASE_PASSWORD});
my $HELMDBC = HelmDB::connect($ENV{DATABASE_NAME},    $ENV{DATABASE_USER}, $ENV{DATABASE_PASSWORD});

#print "got connection to $ENV{IZ_DATABASE_NAME}, $ENV{DATABASE_USER}, $ENV{DATABASE_PASSWORD}\n";
#print "got connection to $ENV{DATABASE_NAME},    $ENV{DATABASE_USER}, $ENV{DATABASE_PASSWORD}\n";

# And close 'em when done:
END {
    $IZDBC->disconnect()   if $IZDBC;
    $HELMDBC->disconnect() if $HELMDBC;    
}

# Swipe the file contents:
open(IN, "< $datafile") || die "Unable to open $datafile for read: $!\n";
while(<IN>){
    # Parse the data file:

    # Skip if empty:
    next unless m/\S/;
    # Skip if comment:
    next if m/^\s*#/;
    
    if( m/^([\S]+)\s+([\S]+)\s*$/ ){
        
        #print "Found line to fold in: $1, $2\n";
        my ($old_email, $scast_username) = ($1, $2);
 
        # NOTE: it seems the right thing to do to lowercase these:
        $old_email      = lc($old_email);
        $scast_username = lc($scast_username);
        
        push( @@{ $scast_user{$scast_username}->{'old'} }, $old_email);
                
    } elsif(m/^([\S]+)\s*$/) {
        print "Found username to delete: $1\n";
        push( @@{ $scast_user{$default_username}->{'old'} }, $1);    
        
    } else {
        print "Line skipped: $_\n";
        push(@@skipped_lines, $_);   
    }
}
close IN;

print "Done parsing $datafile ... \n";

foreach(keys %scast_user){
    
    my $scast_username = $_;
    my $new_iz_uname    = $scast_username;

    # The target should be {username}, but might be {username}@@{project}
    # (in the case of issues@@{project}), or if the user was sloppy, it
    # might be a full email address including the current domain. 
    unless($new_iz_uname =~ m/$ENV{DOMAIN}$/){
        if($new_iz_uname =~ m/\@@/){
            $new_iz_uname .= '.' . $ENV{DOMAIN};
        } else {
            $new_iz_uname .= '@@' . $ENV{DOMAIN};
        }
    }

    my @@old_emails     = @@{ $scast_user{$scast_username}->{'old'} };
    
    my @@groups;
    my @@blessgroups;

    # Add in the minimum role, if specified: 
    if($minimum_role){
        push(@@groups, $helm_roles{$minimum_role}) if $helm_roles{$minimum_role};    
    }
    
    # Sanity check.  Make sure there's a corresponding user in helm
    unless(verify_helm_user($HELMDBC, $scast_username)){
        print "  WARN: No Helm acct found for $scast_username\n"; 
        push(@@missing_scast_users, $scast_username); 
    }
    
    # get the userid of the target IZ account, or create the account
    # if none exists
    unless($scast_user{$scast_username}->{'id'}){
        print "  Getting IZ account info for scast_username ... \n";
        $scast_user{$scast_username}->{'id'} = 
            get_iz_userid_from_username($IZDBC, $new_iz_uname);

        unless($scast_user{$scast_username}->{'id'}){
            print "    No info found.  Creating account for $new_iz_uname\n";
            create_iz_account($IZDBC, $new_iz_uname);
            $scast_user{$scast_username}->{'id'} = 
                get_iz_userid_from_username($IZDBC, $new_iz_uname);
                
            # note that the acct. was created:
            push(@@created_iz_accts, $new_iz_uname);             
        }
    }
    
    my $new_iz_id = $scast_user{$scast_username}->{'id'};
    
    # Iterate over the old accts., disabling
    foreach(@@old_emails){
        my $old_iz_uname = $_;
        my $old_iz_id = get_iz_userid_from_username($IZDBC, $old_iz_uname);
        
        unless($old_iz_id){
            print "  WARN: no IZ userid found for $old_iz_uname\n";
            push(@@missing_iz_users, $old_iz_uname);
            next;
        }
                
        print "    Getting role data from $old_iz_uname\n";
        
        my $gs  = select_one_cell($IZDBC, "SELECT groupset FROM profiles WHERE userid      = $old_iz_id");
        my $bgs = select_one_cell($IZDBC, "SELECT blessgroupset FROM profiles WHERE userid = $old_iz_id");
        
        # Store the bitsets for groups and blessgroups.  Perl doesn't handle
        # 64-bit math, so we store them to let mysql do the work;
        push( @@groups,      $gs );
        push( @@blessgroups, $bgs );
        
        print "      Transferring responsibility from $old_iz_uname to $scast_username\n";
        transfer_responsibility($IZDBC, $old_iz_id, $old_iz_uname, $new_iz_id, $new_iz_uname);
        
        print "      Scheduling $old_iz_uname for deletion\n";
        push(@@usernames_to_delete, $old_iz_uname);
        
    }
    print "    Updating group info for $scast_username\n";
    update_groupset($IZDBC, $new_iz_uname, @@groups);
    update_blessgroupset($IZDBC, $new_iz_uname, @@blessgroups);
    
    print "  Done processing $scast_username\n";
}
print "Done updating.\n";

print "Deleting users ... \n";
foreach(@@usernames_to_delete){ 
    delete_iz_account($IZDBC, $_); 
}
print "Done deleting.\n";

# Update password/cryptpassword:
update_passwords($IZDBC);

# Report errors, etc.:
print "\nResults:\n";
if(@@usernames_to_delete){
    print "Users deleted from IZ:\n";
    foreach(@@usernames_to_delete){
        print "  $_\n";
    } 
}
if(@@missing_scast_users){
    print "Helm users specified, but not found in HELM_USER:\n";
    foreach(@@missing_scast_users){
        print "  $_\n";
    } 
}
if(@@missing_iz_users){
    print "IZ users specified for deletion, but not found in IZ:\n";
    foreach(@@missing_iz_users){
        print "  $_\n";
    } 
}
if(@@created_iz_accts){
    print "IZ accounts created:\n";
    foreach(@@created_iz_accts){
        print "  $_\n";
    } 
}


## SUBROUTINES #####################################################33

sub help {
    
    $0 =~ m#([^/]+)$#;
    my $scriptname = $1;

    return qq{
$scriptname:
	Takes a tab-delimited datafile containing old email addresses and a target 
Helm username to associate each with, updates IZ's tables by consolidating references
to the old address to the new username, and deletes the old accounts.  Old emails 
without target names are removed after being consolidated under a default user
(defunct_userissues unless specified on the command line).  An optional minimum role 
to grant the resulting accounts can also be specified.

  options:
    
  --datafile=[filename]
        
       tab-delimited datafile, one line per entry in the form:
    '[old_email_address]\t[scast_username]' or '[old_email_address]'
    
  --default_username=[username]
        
       default scast username to assign issues to when deleting users
        
  --minimum_role=[admin|developer|observer]
    
        minimum role to grant resulting account in IZ
    
    \n};
        
}
sub check_errors {
    
    # Got args?:
    unless(@@ARGV){
        print help();
        exit;    
    }
    
    # Got env?
    foreach(qw( DOMAIN DATABASE_NAME IZ_DATABASE_NAME)){
        unless($ENV{$_}){
           print " $_ not set; exiting.\n\n";
           exit;    
        }
    }
}
sub sql_quote {
    my ($dbh, $string) = @@_;
    return($dbh->quote($string));
}

# boolean.  make sure there exists such a user
sub verify_helm_user {
    my ($dbh, $username) = @@_;
    my $sql;
    
    $username = sql_quote($dbh, $username);    
    $sql = qq[SELECT COUNT(*) FROM HELM_USER WHERE LOGIN_NAME = $username];
    
    return(select_one_cell($dbh, $sql));
}
sub get_iz_userid_from_username {
    my ($dbh, $username) = @@_;
    my $sql;
    
    $username = sql_quote($dbh, $username);    
    $sql = qq[SELECT userid FROM profiles WHERE login_name = $username];
    
    return(select_one_cell($dbh, $sql));
}
sub create_iz_account {
    my ($dbh, $username) = @@_;
    my $sql;
    
    $username = sql_quote($dbh, $username);    
    
    return( HelmDB::runSQL($dbh, "INSERT INTO profiles SET login_name = $username") );
}
sub delete_iz_account {
    my ($dbh, $username) = @@_;
    my $sql;
    
    $username = sql_quote($dbh, $username);    

    return( HelmDB::runSQL($dbh, "DELETE FROM profiles WHERE login_name = $username") );    
}
sub update_groupset {
    my ($dbh, $username, @@groups) = @@_;

    push(@@groups, 0); # make sure there's at least one entry  

    my $sql;
    my $groupstring = join(' | ', @@groups);
    
    $username = sql_quote($dbh, $username);
    $sql = qq[ UPDATE profiles SET groupset = $groupstring WHERE login_name = $username ];
    return( HelmDB::runSQL($dbh, $sql) );
}
sub update_blessgroupset{
    my ($dbh, $username, @@groups) = @@_;  

    push(@@groups, 0); # make sure there's at least one entry  

    my $sql;
    my $groupstring = join(' | ', @@groups);
    
    $username = sql_quote($dbh, $username);
    $sql = qq[ UPDATE profiles SET blessgroupset = $groupstring WHERE login_name = $username  ];
    return( HelmDB::runSQL($dbh, $sql) );
}
sub update_passwords {
    my ($dbh) = @@_;
    my $sql = qq[UPDATE profiles SET password = 'password', cryptpassword = encrypt('password') ]; 
    return( HelmDB::runSQL($dbh, $sql) );
}
sub select_one_cell {
    my ($dbh, $sql) = @@_;
    my @@r = HelmDB::runQuery($dbh, $sql);    
    return( $r[0]->[0] );
}
sub transfer_responsibility {
    my ($dbh, $from_id, $from_name, $to_id, $to_name) = @@_;
    
    $from_name = sql_quote($dbh, $from_name);
    $to_name   = sql_quote($dbh, $to_name);
    
    foreach(
        qq[update subcomponents set initialowner = $to_name where initialowner = $from_name],
        qq[update subcomponents set initialqacontact = $to_name where initialqacontact = $from_name],
        
        qq[update attachments set submitter_id = $to_id where submitter_id = $from_id],
        qq[update cc set who = $to_id where who = $from_id],
        qq[update issues set reporter = $to_id where reporter = $from_id],
        qq[update issues set assigned_to = $to_id where assigned_to = $from_id],
        qq[update issues set qa_contact = $to_id where qa_contact = $from_id],
        qq[update issues_activity set who = $to_id where who = $from_id],
        qq[update longdescs set who = $to_id where who = $from_id],
        qq[update votes set who = $to_id where who = $from_id],
        qq[update namedqueries set userid = $to_id where userid = $from_id],
        qq[update watch set watcher = $to_id where watcher = $from_id],
        qq[update watch set watched = $to_id where watched = $from_id],
        
        qq[update profiles_activity set userid = $to_id where userid = $from_id],
        qq[update profiles_activity set who = $to_id where who = $from_id]
    ){ 
        my $rv = HelmDB::runSQL($dbh, $_);
        # print "Running '$_'\n";
    }
    
        
}

__END__








@


1.2
log
@Added allowances for handling target email addresses like 'issues@@{project}',
instead of just {username}.
@
text
@d2 1
a2 1
# $Id: consolidate_iz_users.pl,v 1.1 2001/07/19 00:19:14 kmaples Exp $ 
d189 2
d332 5
@


1.1
log
@Issue number: 4861
Utility script to aid in the consolidation of 'old' IZ accounts when
upgrading from a classic single-db installation.
@
text
@d2 1
a2 1
# $Id: $ 
d98 13
a110 1
    my $new_iz_uname    = "$scast_username\@@$ENV{DOMAIN}";
@

