#!/usr/pkg/bin/perl -w
#
# $Header: /raid/cvsroot/rt/bin/rtadmin,v 1.4 2001/12/14 21:42:58 jesse Exp $
# RT is (c) 1996-2001 Jesse Vincent <jesse@fsck.com>

use strict;
use Carp;
use Getopt::Long qw(:config pass_through);

use lib "/usr/pkg/rt/lib";
use lib "/usr/pkg/rt/etc";

use RT::Interface::CLI  qw(CleanEnv LoadConfig DBConnect 
			   GetCurrentUser GetMessageContent);

#Clean out all the nasties from the environment
CleanEnv();

#Load etc/config.pm and drop privs
LoadConfig();

#Connect to the database and get RT::SystemUser and RT::Nobody loaded
DBConnect();

#Drop setgid permissions
RT::DropSetGIDPermissions();

#Get the current user all loaded
my $CurrentUser = GetCurrentUser();

unless ($CurrentUser->Id) {
        print "No RT user found. Please consult your RT administrator.\n";   
        exit(1);
}




PickMode();


# {{{ Help

sub Help {

    # {{{ help_acl
my $help_acl ="
        Access control
	--grant-right <right> 
	--revoke-right <right>
	  --userid <user>
          --groupid <group>
	--list-rights";

# }}}
    
    # {{{ help_keyword_sel
my $help_keyword_sel = "
       Keyword Selections
       --add-keyword-select
       --modify-keyword-select <name>
          --ks-name <name>
          --ks-keyword <keyword>
          --ks-single 
          --ks-multiple
          --ks-depth  <int>

        --disable-keyword-select <name>";
# }}}
    
    # {{{ help_scrip
my $help_scrip = "
        Scrips
        --create-scrip
           --scrip-condition <condition name or id>
           --scrip-action <action name or id>
           --scrip-template <template name or id>

        --delete-scrip <id>
	--list-scrips";

# }}}
    
    # {{{ help_template  
my $help_template = "      
        Templates
        --delete-template [<id>|<name>]
        --display-template [<id>|<name>]

         --create-template
         --modify-template [<id>|<name>]
           Flags for --create-template and --modify-template
           --template-name
           --template-description
           --template-edit-content
         
         --list-templates";

# }}}
    
    
print <<EOF;

USAGE:  rtadmin --user <userid> [Userflags]
	rtadmin --list-users
	rtadmin --queue <queueid> [Queueflags]
	rtadmin --list-queues
	rtadmin --group [groupflags]
	rtadmin --list-groups
	rtadmin --system  [SystemFlags]
	rtadmin --keyword [keywordflags]

User configuration for --user <userid>
   
  	--disable
  	--create
	--display

  Core Attributes
	--userid
	--gecos
	--password
	--emailaddress
	--privileged
	--comments
	--signature
	--organization

  Names	
	--realname
	--nickname
	
  Auth and external info
	--externalcontactinfoid
	--contactinfosystem
	--externalauthid
	--authsystem

  Phone numbers
	--pagerphone
	--workphone
	--mobilemphone
	--homephone

  Paper address
	--address1
	--address2
	--city
	--state
	--zip
	--country
	--freeformcontactqinfo	


Group Configuration for --group <groupid>
	--create 
	--delete
	--display

	--name <new name>
	--description <new description>



	--add-member <userid>
	--delete-member <userid>
	--list-members	

Queue Configuration for --queue <queueid>
	--create
	--disable
	--display

	--name <name>
	--correspondaddress <email address>
	--commentaddress <email address>
	--initialpriority <int>
	--finalpriority <int>
	--defaultduein <days>

	--add-cc <email address>
	--delete-cc <email address>
	--add-admincc <email address>
	--delete-admincc <email address>
        --list-watchers

	

$help_acl

$help_keyword_sel

$help_template

$help_scrip


System configuration for --system 

$help_acl

$help_keyword_sel

$help_template

$help_scrip


Keyword configuration for --keyword  <fully qualified name>
	--list-children
  	--create-child <name>
	--disable
	--name <new name>
	--description <new description>

EOF



}

# }}}

# {{{ PickMode

sub PickMode {
    my ($user,$group, $queue, $system, $keyword, $listusers, 
	$listgroups, $listqueues, $help);


    GetOptions ('help|h|usage' => \$help,
		'user=s' => \$user,
		'queue=s' => \$queue,
		'group=s' => \$group,
		'system' => \$system,
		'keyword=s', => \$keyword,
		'list-users' => \$listusers,
		'list-queues' => \$listqueues,
		'list-groups' => \$listgroups,
	       );
    

    
    if ($user)          { AdminUser($user) }  
    elsif ($group)      { AdminGroup($group) }
    elsif ($queue)      { AdminQueue($queue) }
    elsif ($system)     { AdminSystem($system) }
    elsif ($keyword)    { AdminKeywords($keyword) }
    elsif ($listusers)  { ListUsers() }
    elsif ($listgroups) { ListGroups()  }
    elsif ($listqueues) { ListQueues() }
    elsif ($help)       { Help()}
    else {
	print "No command found\n";
    }
    exit(0);
}	

# }}}

# {{{ AdminUser

sub AdminUser {
    my $user=shift;
    my %args;

    GetOptions(\%args,
	   'create', 'disable|delete', 'display',
	   'Name=s', 'Gecos=s', 'Password=s',
	   'EmailAddress=s', 'Privileged=s', 'Comments=s', 'Signature=s',
	   'Organization=s', 'RealName=s', 'NickName=s',  
	   'ExternalContactInfoId=s', 'ContactInfoSystem=s', 
           'ExternalAuthId=s', 'AuthSystem=s',
	   'HomePhone=s', 'WorkPhone=s', 'MobilePhone=s', 'PagerPhone=s',
           'Address1=s', 'Address2=s', 'City=s', 'State=s', 'Zip=s', 
           'Country=s', 'FreeformContactInfo=s');

    my $user_obj = new RT::User($CurrentUser);
    
 
    #Create the user if we need to 
    if ($args{'create'}) {
	my ($status, $msg) = 
	  $user_obj->Create( Name => ($args{'Name'} || $user),
			     Gecos => $args{'Gecos'},
			     Password => $args{'Password'},
			     EmailAddress => $args{'EmailAddress'},
			     Privileged => $args{'Privileged'},
			     Comments => $args{'Comments'},
			     Signature => $args{'Signature'},
			     Organization => $args{'Organization'},
			     RealName => $args{'RealName'},
			     NickName => $args{'NickName'},
			     ExternalContactInfoId => $args{'ExternalContactInfoId'},
			     ContactInfoSystem => $args{'ContactInfoSystem'},
			     ExternalAuthId => $args{'ExternalAuthId'},
			     AuthSystem => $args{'AuthSystem'},
			     HomePhone => $args{'HomePhone'},
			     WorkPhone => $args{'WorkPhone'},
			     MobilePhone => $args{'MobilePhone'},
			     PagerPhone => $args{'PagerPhone'},
			     Address1 => $args{'Address1'},
			     Address2 => $args{'Address2'},
			     City  => $args{'City'},
			     State => $args{'State'},
			     Zip => $args{'Zip'},
			     FreeformContactInfo => $args{'FreeformContactInfo'}
			   );
	
	print "$msg\n";
	return();
	
    }
    else {
	
	
	#Load the user
	$user_obj->Load($user);
	
	unless ($user_obj->id) {
	    print "User '$user' not found\n";
	    return();
	}	
	
	
	
	#modify the user if we need to
	my @attributes = ('Name', 'Gecos',
			  'EmailAddress', 'Privileged', 'Comments', 'Signature',
			  'Organization', 'RealName', 'NickName',  
			  'ExternalContactInfoId', 'ContactInfoSystem', 
			  'ExternalAuthId', 'AuthSystem',
			  'HomePhone', 'WorkPhone', 'MobilePhone', 'PagerPhone',
			  'Address1', 'Address2', 'City', 'State', 'Zip', 
			  'Country', 'FreeformContactInfo');
	foreach my $attrib (@attributes) {
	    if ( (exists ($args{"$attrib"})) and
		 ($user_obj->$attrib() ne $args{"$attrib"})) {
		
		my $method = "Set$attrib";
		my ($val, $msg) = $user_obj->$method($args{"$attrib"});
		print "User ".$user_obj->Name. " $attrib:  $msg\n";
		
	    }
	}		
	
	if (exists ($args{'Password'})) {
	    my ($code, $msg);
	    ($code, $msg) = $user_obj->SetPassword($args{'Password'});
	    print "User ". $user_obj->Name. ' Password: '. $msg . "\n";
	}
	
	#Check if we need to display the user
	if ($args{'display'}) {
	    foreach my $attrib (@attributes) {
		next if ($attrib eq 'Password'); #Can't see the password
		printf("%22.22s %-64s\n",$attrib, ($user_obj->$attrib()||'(undefined)'));
		
	    }	
	}	
	
	#Check if we need to delete the user
	if ($args{'disable'}) {
	    my ($val, $msg) = $user_obj->SetDisabled(1);
	    print "$msg\n";
	}	
	
    }
}

# }}}

# {{{ AdminQueue

sub AdminQueue {
    my $queue=shift;
    my %args;

    GetOptions(\%args,
	       'create', 'disable|delete', 'display',
	       'Name=s', 'CorrespondAddress=s', 'Description=s',
	       'CommentAddress=s', 'InitialPriority=n', 'FinalPriority=n',
	       'DefaultDueIn=n',
	       
	       'add-cc=s@', 'add-admincc=s@', 
	       'delete-cc=s@', 'delete-admincc=s@',
	       'list-watchers', 'create-template'
	       );

    use RT::Queue;
    my $queue_obj = new RT::Queue($CurrentUser);
    
    #Create the queue if we need to 
    if ($args{'create'}) {
	my ($status, $msg) = 
	  $queue_obj->Create(
			     Name => ($args{'Name'} || $queue) ,
			     CorrespondAddress => $args{'CorrespondAddress'},
			     Description => $args{'Description'},
			     CommentAddress  => $args{'CommentAddress'},
			     InitialPriority => $args{'InitialPriority'},
			     FinalPriority => $args{'FinalPriority'},
			     DefaultDueIn => $args{'DefaultDueIn'}
			    );
	
	print "$msg\n";
    }
    else {
	#Load the queue
	$queue_obj->Load($queue);
	
	unless ($queue_obj->id) {
	    print "Queue '$queue' not found\n";
	    return();
	}	
		
        #modify if we need to
	my @attributes = qw(Name CorrespondAddress Description
			    CommentAddress InitialPriority FinalPriority
			    DefaultDueIn
			 );
	foreach my $attrib (@attributes) {
	    if ( (exists ($args{"$attrib"})) and
		 ($queue_obj->$attrib() ne $args{"$attrib"})) {
		
		my $method = "Set$attrib";
		my ($val, $msg) = $queue_obj->$method($args{"$attrib"});
		print "Queue ".$queue_obj->Name. " $attrib:  $msg\n";
		
	    }
	}		
	    
	
	#Check if we need to display the queue
	if ($args{'display'}) {
	    foreach my $attrib (@attributes) {
		printf("%22.22s %-64s\n",$attrib, ($queue_obj->$attrib()||'(undefined)'));
		
	    }	
	}	
       	
	foreach my $person (@{$args{'add-cc'}}) {
	    my ($val, $msg) = $queue_obj->AddCc(Email => $person);
	    print "$msg\n";
	}
	foreach my $person (@{$args{'add-admincc'}}) {
	    my ($val, $msg) = $queue_obj->AddAdminCc(Email => $person);
	    print "$msg\n";
	}

	foreach my $person (@{$args{'delete-cc'}}) {
	    my ($val, $msg) = $queue_obj->DeleteCc($person);
	    print "$msg\n";
	}
	foreach my $person (@{$args{'delete-admincc'}}) {
	    my ($val, $msg) = $queue_obj->DeleteAdminCc($person);
	    print "$msg\n";
	}

	if ($args{'list-watchers'}) {
	    require RT::Watchers;
	    my $watchers = new RT::Watchers($CurrentUser);
	    $watchers->LimitToQueue($queue_obj->id);
	    while (my $watcher = $watchers->Next()) {
		printf("%10s %-60s\n",
		       $watcher->Type, $watcher->Email );
	    }	
	}	

        AdminTemplates($queue_obj->Id());
        AdminScrips($queue_obj->Id());
	AdminRights($queue_obj->Id());
	AdminKeywordSelects($queue_obj->Id());

	#Check if we need to delete the queue
	if ($args{'disable'}) {
	    my ($val, $msg) = $queue_obj->SetDisabled(1);
	    print "$msg\n";
	}	
	
    }
}

# }}}

# {{{ AdminKeywords

sub AdminKeywords {
    my $keyword = shift;
    
    my %args;
    GetOptions(\%args, 'list-children', 'create-child=s', 'disable|delete', 'Name=s', 'Description=s');
    
    use RT::Keyword;
    
    my $key_obj = new RT::Keyword($CurrentUser);
    my $key_id;
    
    #If we're dealing with the root of the keyword list
    if ($keyword eq '/') {
	$key_id=0;
    }	
    else {
	my ($val, $msg) = $key_obj->LoadByPath( $keyword );
	unless ($val) {
	    print $msg ."\n";
	}
	$key_id = $key_obj->Id();
    }	
    
    if ($args{'create-child'}) {
	my $child = new RT::Keyword($CurrentUser);
	
	my ($val, $msg) = $child->Create( Parent => $key_id,
					  Name => $args{'create-child'},
					);
	print $msg ."\n";
    }	
    
    elsif ($args{'list-children'}) {
	my $keywords;
	if ($key_obj->id) {
	    $keywords = $key_obj->Children();
	}	
	#If we didn't actually have a keyword object, we need to create our own Keywords object.
	else {
	    $keywords = new RT::Keywords($CurrentUser);
	    $keywords->LimitToParent(0); 
	}
	
	while (my $key=$keywords->Next) {
	    print $key->Name;
	    if ($key->Description) {
		print " (" . $key->Description .")";
	    }	
	    print "\n";
	}	
	      

    }	
    
    #Else we wanna do some modification.
    else {
	
	#If we didn't load a keyword, get out
	return(undef) unless ($key_obj->Id);
	
	
	my @attributes = qw( Name Description );
	foreach my $attrib (@attributes) {
	    if ( (exists ($args{"$attrib"})) and
		 ($key_obj->$attrib() ne $args{"$attrib"})) {
		
		my $method = "Set$attrib";
		my ($val, $msg) = $key_obj->$method($args{"$attrib"});
		
		print "Keyword ".$key_obj->Name. " $attrib:  $msg\n";	    }
	}
	
	if ($args{'disable'}) {
	    $key_obj->SetDisabled(1);
	    
	}
	
    }
}

# }}}

# {{{ AdminKeywordSelects

sub AdminKeywordSelects {
    my $queue = shift;
    # O for queue means global

    my %args;
    GetOptions(\%args, 'add-keyword-select','disable-keyword-select|delete-keyword-select=s',
	       'modify-keyword-select=s', 
	       'keyword-select-Keyword|ks-keyword=s', 
	       'keyword-select-Single|ks-single', 
	       'keyword-select-Multiple|ks-multiple', 
	       'keyword-select-Depth|ks-depth=i', 
	       'keyword-select-Name|ks-name=s'
	      );

    # sanitize single vs multiple.
    if ($args{'keyword-select-Multiple'}) {
	$args{'keyword-select-Single'} = 0;
    }
    
    use RT::KeywordSelect;
    my $keysel_obj = new RT::KeywordSelect($CurrentUser);
    if ($args{'add-keyword-select'}) {
	
	my ($val, $msg) = $keysel_obj->Create( Keyword => $args{'keyword-select-Keyword'},
					       Depth => $args{'keyword-select-Depth'},
					       Single => $args{'keyword-select-Single'},
					       Name => $args{'keyword-select-Name'},
					       ObjectType => 'Ticket',
					       ObjectField => 'Queue',
					       ObjectValue => $queue);
	print $msg ."\n";
    }	
    elsif ($args{'modify-keyword-select'}) {
	$keysel_obj->LoadByName(Name => $args{'modify-keyword-select'},
				Queue => $queue
			       );
	
	unless ($keysel_obj->Id()) {
	    print "Keyword select not found\n";
	    return();
	}	
	my @attributes = qw( Name Keyword Single Depth );
	foreach my $attrib (@attributes) {
	    if ( (exists ($args{"keyword-select-$attrib"})) and
		 ($keysel_obj->$attrib() ne $args{"keyword-select-$attrib"})) {
		
		my $method = "Set$attrib";
		my ($val, $msg) = $keysel_obj->$method($args{"keyword-select-$attrib"});
				
		print "Keyword select ".$keysel_obj->Name. " $attrib:  $msg\n";	    }
	}


    }	

    
    elsif ($args{'disable-keyword-select'}) {
	$keysel_obj->LoadByName(Name => $args{'disable-keyword-select'},
				Queue => $queue);
	
	$keysel_obj->SetDisabled(1);
	
    }
}

# }}}

# {{{ AdminGroup

sub AdminGroup {
    my $group = shift;

    my (%args);

    GetOptions(\%args,
	       'create', 'delete', 'display',
	       'Name=s', 'Description=s',
	       	       
	       'add-member=s@', 'delete-member=s@',
	       'list-members'
	       );


    use RT::Group;
    my $group_obj = new RT::Group($CurrentUser);
    unless ($group) {
	print "Group not specified.\n";
	return();
    }	
    

    #Create the group if we need to
    if ($args{'create'}) {
	my ($val, $msg) = $group_obj->Create( Name => ($args{'Name'} || $group),
					      Description => $args{'Description'} );
	print $msg ."\n";
    }	
    #otherwise we load it
    else {
	$group_obj->Load($group);
    }	
    
    #If we have no group object, get the hell out
    unless ($group_obj->Id) {
	print "Group not found.\n";
    }

    if ($args{'delete'}) {
	my ($val, $msg) = $group_obj->Delete();
	print $msg ."\n";
	return();
    }	


    
    #modify if we need to
    my @attributes = qw(Name Description
			
		       );
    foreach my $attrib (@attributes) {
	if ( (exists ($args{"$attrib"})) and
	     ($group_obj->$attrib() ne $args{"$attrib"})) {
		
	    my $method = "Set$attrib";
	    my ($val, $msg) = $group_obj->$method($args{"$attrib"});
	    print "Group ".$group_obj->Name. " $attrib:  $msg\n";
	    
	    }
    }		
    
    foreach my $user (@{$args{'add-member'}}) {
	my ($val, $msg) = $group_obj->AddMember($user);
	print $msg. "\n";
    }
    foreach my $user (@{$args{'delete-member'}}) {
	my ($val, $msg) = $group_obj->DeleteMember($user);
	print $msg ."\n";
    }
    
    if ($args{'list-members'}) {
	my $members = $group_obj->MembersObj();
	while (my $member = $members->Next()) {
	    print $member->UserObj->Name() ."\n";
	}
    }	
    
}

# }}}

# {{{ AdminSystem
sub AdminSystem {
    print "In AdminSystem\n";

    AdminTemplates(0);
    AdminScrips(0);
    AdminRights(0);
    AdminKeywordSelects(0);
}
# }}}

# {{{ sub AdminTemplates

sub AdminTemplates {
    my $queue = shift;
    #Queue = 0 means 'global';

    my %args;

    
    GetOptions(\%args, 'list-templates', 'create-template','modify-template=s',
	       'delete-template=s', 'display-template=s',
	       'template-Name=s', 'template-Description=s',
	       'template-edit-content!');
    
    # {{{ List templates
    if ($args{'list-templates'}) {
	print "Templates for $queue\n";
	require RT::Templates;
	my $templates = new RT::Templates($CurrentUser);
	if ($queue != 0) {
	    $templates->LimitToQueue($queue);
	}	
	else {
	    $templates->LimitToGlobal();
	}	
	while (my $template = $templates->Next) {
	    print $template->Id.": ".$template->Name." - " . $template->Description ."\n";
	}	
    }

    # }}}

    require RT::Template;	
    my $template = new RT::Template($CurrentUser);
    if ($args{'delete-template'}) {
	$template->Load($args{'delete-template'});
	unless ($template->id) {
	    print "Couldn't load template";
	    return(undef);
	}
	my ($val, $msg) = $template->Delete();
	print "$msg\n";
    }
    elsif ($args{'create-template'}) {
	#TODO edit the template content
	my $content;

	my $linesref = GetMessageContent(CurrentUser => $CurrentUser,
				      Edit => 1);
	
	$content = join("\n", @{$linesref});
	

	my ($val, $msg) = $template->Create(Name => $args{'template-Name'},
					    Description => $args{'template-Description'},
					    Content => $content,
					    Queue => $queue);
	print "$msg\n";
    }	
    elsif ($args{'modify-template'}) {
	
	$template->Load($args{'modify-template'});
	unless ($template->Id()) {
	    print "Template not found\n";
	    return();
	}	
	my @attributes = qw( Name Description );
	foreach my $attrib (@attributes) {
	    if ( (exists ($args{"template-$attrib"})) and
		 ($template->$attrib() ne $args{"template-$attrib"})) {
		
		my $method = "Set$attrib";
		my $val = $template->$method($args{"template-$attrib"});
				
	    }
	}
	if ($args{'template-edit-content'}) {
	    
	    my $linesref = GetMessageContent(CurrentUser => $CurrentUser,
					     Content => $template->Content,
					     Edit => 1);
	    
	    my $content = join("\n", @{$linesref});	    
	    my ($val) = $template->SetContent($content);
	    print $val."\n";
	}	

    }	
    if ($args{'display-template'}) {
	$template->Load($args{'display-template'});
	print $template->Name . "\n". $template->Description ."\n". $template->Content."\n";
    }	
}	

# }}}

# {{{ sub AdminScrips

sub AdminScrips {
    my $queue = shift;
    #Queue = 0 means 'global';

    my %args;

    
    GetOptions(\%args, 'list-scrips', 'create-scrip','modify-scrip=s',
	       'scrip-action=s', 'scrip-template=s', 'scrip-condition=s',
	       'delete-scrip=s');

    
    # {{{ List entries
    if ($args{'list-scrips'}) {
	print "Scrips for $queue\n";
	require RT::Scrips;
	my $scrips = new RT::Scrips($CurrentUser);
	if ($queue != 0) {
	    $scrips->LimitToQueue($queue);
	}	
	else {
	    $scrips->LimitToGlobal();
	}	
	while (my $scrip = $scrips->Next) {
	    print $scrip->Id.": If ".
	      $scrip->ConditionObj->Name." then " .
		$scrip->ActionObj->Name." with template " .
		  $scrip->TemplateObj->Name."\n";
	}	
    }

    # }}}

    require RT::Scrip;
    my $scrip = new RT::Scrip($CurrentUser);
    if ($args{'delete-scrip'}) {
	$scrip->Load($args{'delete-scrip'});
	unless ($scrip->id) {
	    print "Couldn't load scrip";
	      return(undef);
	}
	my ($val, $msg) = $scrip->Delete();
	print "$msg\n";
    }
    elsif ($args{'create-scrip'}) {
	my ($val, $msg) = $scrip->Create( ScripAction => $args{'scrip-action'},
					  ScripCondition => $args{'scrip-condition'},
					  Template => $args{'scrip-template'},
					  Queue => $queue);

	print "$msg\n";
    }	
}	

# }}}

# {{{ sub AdminRights

sub AdminRights {
    my $queue = shift;
    #Queue = 0 means 'global';

    my ($scope, $appliesto);
    if ($queue == 0) {
	$scope = 'System';
	$appliesto = 0;
    }	
    else {
	$scope =  'Queue';
	$appliesto = $queue;
    }	

    my %args;    
    GetOptions(\%args, 
	       'grant-right|add-right|new-right|create-right=s@',
	       'revoke-right|del-right|delete-right=s@',
	       'list-rights', 'userid=s@', 'groupid=s@',
	      );
    
    
    # {{{ List entries
    if ($args{'list-rights'}) {
	require RT::ACL;
	my $acl = new RT::ACL($CurrentUser);
	if ($queue != 0) {
	    $acl->LimitToQueue($queue);
	}	
	else {
	    $acl->LimitToSystem();
	}	
	while (my $ace = $acl->Next) {
	    print $ace->RightScope;
	    
	    #Print the queue name if we have it.
	    print " " . $ace->AppliesToObj->Name if (defined $ace->AppliesToObj);
	    
	    print ": ". $ace->PrincipalType . " " .$ace->PrincipalObj->Name .
	      " has right " . $ace->RightName ."\n";
	      
	}	
    }

    # }}}

    require RT::ACE;    

    # {{{ Build up an array of principals
    my (@principals);
    my $i = 0;
    foreach my $group (@{$args{'groupid'}}) { 


	my $princ = new RT::Group($CurrentUser);
	$princ->Load("$group");
	if ($princ->id) {
	    $principals[$i]->{'type'} = 'Group';
	    $principals[$i]->{'id'} = $princ->id();
	    $i++;
	}	
	else {
	    print "Could not find group $group\n";
	}	
    }	


    foreach my $user (@{$args{'userid'}}) { 
	my $princ = new RT::User($CurrentUser);
	$princ->Load("$user");
	if ($princ->id) {
	    $principals[$i]->{'type'} = 'User';
	    $principals[$i]->{'id'} = $princ->id();
	    $i++;
	}	
	else {
	    print "Could not find user $user.\n";
	    }
    }
    # }}}


    foreach my $principal (@principals) {

	# {{{ Delete rights that need deleting
	foreach my $right (@{$args{'revoke-right'}}) {
	    my $ace = new RT::ACE($CurrentUser);
	    $RT::Logger->debug("Trying to delete a right: $right \n");
	    my ($val, $msg) = $ace->LoadByValues( RightName => $right,
						  RightScope => $scope,
						  PrincipalType => $principal->{'type'},
						  PrincipalId => $principal->{'id'},
						  RightAppliesTo => $appliesto);
	    
	    unless ($val) {
		print "Right $right not found for" . $principal->{'type'} . " " .
		  $principal->{'id'} . " in scope $scope ($appliesto)\n";
		next;
	    }	
	    my ($delval, $delmsg) =$ace->Delete;
	    print "$delmsg\n";
	    
	    
	}

	# }}}
	
	# {{{ grant rights that need granting
	foreach my $right (@{$args{'grant-right'}}) {
	    my $ace = new RT::ACE($CurrentUser);
	    my ($val, $msg) = $ace->Create(RightName => $right,
					   PrincipalType => $principal->{'type'},
					   PrincipalId => $principal->{'id'},
					   RightScope => $scope,
					   RightAppliesTo => $appliesto);
	    
	    print $msg . "\n";
	}

	# }}}
    }	

}

# }}}


sub ListUsers {
    require RT::Users;
    my $users = new RT::Users($CurrentUser);
    $users->UnLimit();
    while (my $user = $users->Next()) {
	printf ("%16s %-16s\n",$user->Name(), $user->EmailAddress());
    }
}
sub ListQueues {
    require RT::Queues;
    my $queues = new RT::Queues($CurrentUser);
    $queues->UnLimit();
    while (my $queue = $queues->Next()) {
	printf ("%16s %-16s\n",$queue->Name(), $queue->Description());
    }
}

sub ListGroups {
    require RT::Groups;
    my $groups = new RT::Groups($CurrentUser);
    $groups->UnLimit();
    while (my $group = $groups->Next()) {
	printf ("%16s %-16s\n",$group->Name(), $group->Description());
    }	
}
