#!/usr/bin/perl
#
# install-db
#
# Copyright 1999 -- 2001, onShore Development Inc. <URL:http://www.onshore-devel.com/>
#
#
# This program is free software under the terms of the GNU General Public
# License (GPL). A copy of the GPL, "COPYING", should have been made
# available with this software.  If not, a copy may be obtained at 
# http://www.fsf.org/copyleft/gpl.html
#
# $Id: install-db,v 1.21 2001/08/29 22:22:59 adam Exp $
#
$|=1; 
use Getopt::Long; 

sub usage { 
    print "Usage:\n\tinstall-db -db database-type -dbowner database-owner -dbuser database_user_account -sql_interpreter sql_interpreter -sql_directory sql_directory -admin_last admin_last_name -admin_middle admin_middle_name -admin_first admin first name -admin_mail admin_mail_address\n"; 
}

$usergroup = 'appserver';	# hardcoded for now

&GetOptions ( 
	      "db=s" => \$db, 
	      "dbowner=s" => \$dbowner, 
	      "dbuser=s" => \$dbuser, 
	      "sql_interpreter=s" => \$sql_interpreter, 
	      "sql_directory=s" => \$sql_directory, 
	      "dbname=s" =>  \$dbname, 
	      "admin_first=s" => \$admin_first, 
	      "admin_middle=s" => \$admin_middle, 
	      "admin_last=s" => \$admin_last, 
	      "admin_mail=s" => \$admin_mail,
	      "create_guest=s" => \$create_guest,
	      ); 

# make sure all arguments were given
if ( ! ( $db & $dbowner & $dbuser & $sql_interpreter & $dbname
	 & $sql_directory & $admin_last & $admin_mail ) ) { 
    usage();
    exit 1;
}

# make sure dbowner exists
getpwnam($dbowner)
    or die "ERROR: database owner '$dbowner' does not exist\n";

# make sure dbuser exists
($junk, $junk, $dbuseruid, $junk) = getpwnam($dbuser)
    or die "ERROR: user '$dbuser' does not exist. \n";

if ( $db eq "postgres" ) {
    # set our sql intepreter options
    @sql_interp_list = ( $sql_interpreter, '-d', $dbname, '-t', '-q' );

    print "Creating postgres database...\n"; 
    system('createdb', $dbname) == 0
	or die "ERROR: 'createdb' exited with error\n";
    print "  done.\n";

    print "Checking postgres version...\n";
    $pgver = 0;
    open(DB_SHELL, 
	 join(' ', './install/check-pg-version', '-dbname', $dbname, '-sql_interpreter', $sql_interpreter)
	 . "|")
	or die "ERROR: 'check-pg-version' exited with error\n";
    local $SIG{PIPE} = sub { die "ERROR: 'check-pg-version' pipe broke\n" };
    $pgver = <DB_SHELL>;
    close DB_SHELL;
    if ( $pgver < 6.4 ) {
        die "WARNING: obsolete version of postgresql installed, get 6.4 or better\n";    
	if ( $dbuser =~ /-/ ) { 
	    die "ERROR: user \"$dbuser\" contains a \"-\" -- only postgresql versions 6.4
    or higher support this.  You must upgrade postgresql for timesheet to work.\n"; 
	}
    }

    print "Checking whether user '$dbuser' already exists...\n";
    open(DB_SHELL, 
	 join(" ", @sql_interp_list, '-c', 
	      "\"select usename from pg_user where usename = '$dbuser'\"")
	 . "|")
	or die "ERROR: '$sql_interpreter' exited with error\n";
    local $SIG{PIPE} = sub { die "ERROR: '$sql_interpreter' pipe broke\n" };
    $_ = <DB_SHELL>;
    close DB_SHELL
	or die "ERROR: '$sql_interpreter' exited with error\n";
    if ( ! /^\s*$/m ) {
	print "  yes, user with that name exists, skipping user creation\n";
    }
    else {
	open(DB_SHELL, 
	     join(" ", @sql_interp_list, '-c', 
		  "\"select usename from pg_user where usesysid = '$dbuseruid'::int4\"")
	     . "|")
	    or die "ERROR: '$sql_interpreter' exited with error\n";
	$_ = <DB_SHELL>;
	close DB_SHELL
	    or die "ERROR: '$sql_interpreter' exited with error\n";
	if ( ! /^\s*$/m ) {
	    print "  yes, user id $dbuseruid exists, skipping user creation\n";
	}
	else {
	    print "  no.\n";
	    print "Creating database user account for '$dbuser'...\n";
	    open (DB_SHELL, "| createuser $dbuser > /dev/null")
		or die "ERROR: cannot run 'createdb'\n";
	    local $SIG{PIPE} = sub { die "ERROR: 'createdb' pipe broke\n" };
	    select DB_SHELL; $|=1; select STDOUT; 
	    
	    print DB_SHELL "$dbuseruid\n";  # Enter user's postgres ID or RETURN...
	    print DB_SHELL "n\n"; # Is user ... allowed to create databases (y/n)
	    print DB_SHELL "n\n"; # Is user ... allowed to add users? (y/n)
	    close DB_SHELL
		or die "ERROR: 'createdb' exited with error\n";
	    print "  done.\n";
	}
    }

    print "Checking for group '$usergroup'...\n";
    open(DB_SHELL, 
	 join(" ", @sql_interp_list, '-c', 
	      "\"select grosysid from pg_group where groname = '$usergroup'\"")
	 . "|")
	or die "ERROR: '$sql_interpreter' exited with error\n";
    $_ = <DB_SHELL>;
    close DB_SHELL
	or die "ERROR: '$sql_interpreter' exited with error\n";
    if ( ! /^\s*$/m ) {
	s/\s+//g;
	print "  yes, group (id $_) exists, skipping group creation\n";
	print "Checking group membership for user '$dbuser'...\n";
	open(DB_SHELL, 
	     join(" ", @sql_interp_list, '-c', 
		  "\"select grolist from pg_group where " .
		  "groname = '$usergroup'\"")
	     . "|")
	or die "ERROR: '$sql_interpreter' exited with error\n";
	$_ = <DB_SHELL>;
	close DB_SHELL
	    or die "ERROR: '$sql_interpreter' exited with error\n";
	chomp;
	if ( /^\s*$/m ) {
	    print "  no users in group; adding '$dbuser' to group...\n";
	    open(DB_SHELL, 
		 join(" ", @sql_interp_list, '-c', 
		      "\"update pg_group set grolist = '{$dbuseruid}' " .
		      "where groname = '$usergroup'\"")
		 . "|")
		or die "ERROR: '$sql_interpreter' exited with error\n";
	    $_ = <DB_SHELL>;
	    close DB_SHELL
		or die "ERROR: '$sql_interpreter' exited with error\n";
	    print "  done.\n";
	}
	else {
	    # get our current ids
	    local(@grolist);
	    local($foundit) = 0;
	    local($tmp);
	    s/[{}]//g;
	    s/\s+//g;
	    @grolist = split(/[,]/, $_);
	    # print "$_ joins as " . join("|", @grolist);
	    foreach $tmp (@grolist) {
		if ( $tmp == $dbuseruid ) {
		    $foundit = 1;
		    break;
		}
	    }
	    if ( $foundit ) {
		print "  yes.\n";
	    }
	    else {
		print "  no.\n";
		print "Adding user '$dbuser' to group '$usergroup'...\n";
		push(@grolist, $dbuseruid);
		$tmp = join(',', @grolist);
		open(DB_SHELL, 
		     join(" ", @sql_interp_list, '-c', 
			  "\"update pg_group set grolist = '{$tmp}' " .
			  "where groname = '$usergroup'\"")
		     . "|")
		    or die "ERROR: '$sql_interpreter' exited with error\n";
		$_ = <DB_SHELL>;
		close DB_SHELL
		    or die "ERROR: '$sql_interpreter' exited with error\n";
		print "  done.\n";
	    }
	}
    }
    else {
	print "  no.\n";
	warn("FIXME: this might fail if you have a grosysid 1234 already");
	print "Creating group '$usergroup', with member '$dbuser'...\n";
	open(DB_SHELL, 
	     join(" ", @sql_interp_list, '-c', 
		  "\"insert into pg_group (groname, grosysid, grolist) " .
		  "values ('$usergroup', '1234', '{$dbuseruid}')\"")
	     . "|")
	    or die "ERROR: '$sql_interpreter' exited with error\n";
	$_ = <DB_SHELL>;
	close DB_SHELL
	    or die "ERROR: '$sql_interpreter' exited with error, msg '$_'\n";
	print "  done.\n";
    }
} else {
    die "ERROR: database '$db' not supported\n";
}


# theoretically, none of this is very database dependant

print "Creating tables...\n";
system(@sql_interp_list, '-f', "$sql_directory/tables.sql") == 0
    or die "ERROR: '$sql_interpreter' exited with error\n";
print "  done.\n";

print "Creating indices...\n"; 
system(@sql_interp_list, '-f', "$sql_directory/indices.sql") == 0
    or die "ERROR: '$sql_interpreter' exited with error\n";
print "  done.\n";

print "Granting access permissions for user '$dbuser'...\n"; 
@args = ( @sql_interp_list, '-c', 
	  "grant select, update, insert, delete on " .
	  "client, hours, personnel, category, job to group $usergroup;");
system(@args) == 0
    or die "ERROR: '" . join(" ", @args) . "' exited with error\n";
print "  done.\n";

print "Creating timesheet admin user 'admin'..."; 
system(@sql_interp_list, '-c', 
       "insert into personnel (personnel_id, first_name, " .
       "middle_name, last_name, email, super_user)  values " .
       "('admin', '$admin_first', '$admin_middle', " . 
       "'$admin_last', '$admin_mail', 'yes');") == 0
    or die "ERROR: '$sql_interpreter' exited with error\n";
print "\n  done.\n";

if ( $create_guest eq "yes" ) {
    print "Creating timesheet sample user 'guest'..."; 
    system(@sql_interp_list, '-c', 
	   "insert into personnel (personnel_id, first_name, " .
	   "middle_name, last_name, email, super_user)  values " .
	   "('guest', 'Guest', '', 'User', '', '0');") == 0
	       or die "ERROR: '$sql_interpreter' exited with error\n";
    print "\n  done.\n";
}

print "Creating sample client...";
system(@sql_interp_list, '-c', 
       "insert into client (client_id, client_name, " .
       " default_bill_rate, default_approved) values " . 
       "('1', 'Sample Client', '0.00', '0'); " .
       "insert into client (client_id, client_name, " .
       " default_bill_rate, default_approved) values " . 
       "('2', 'Another Sample Client', '0.00', '0'); "
       ) == 0 
       or die "ERROR: '$sql_interpreter' exited with error\n"; 
print "\n  done.\n";

print "Creating default categories...";
foreach $category ( 'Support', 
		    'Support_Emergency', 
		    'Development', 
		    'Development_Emergency', 
		    'Admin', 
		    'Training', 
		    'Emergency'
		    ) { 
    system(@sql_interp_list, '-c', 
	   "insert into category (category_id, creator_id) values " . 
	   "('$category', 'admin')" ) == 0
	       or die "ERROR: '$sql_interpreter' exited with error\n"; 
}
print "\n  done.\n";
print "\nDatabase creation successful.\n"; 
