[Rt-commit] rtir branch, 3.4/add-constituency-lib, created. 3.3.0-103-gfa28f33

Shawn Moore shawn at bestpractical.com
Wed May 25 14:58:30 EDT 2016


The branch, 3.4/add-constituency-lib has been created
        at  fa28f3334dceed1a3d03a798147e7dfd160fdf6f (commit)

- Log -----------------------------------------------------------------
commit 224b3c3bf35bfea6509f03f0988dc8dfef661ea1
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Wed May 25 16:39:14 2016 +0000

    Add scaffolding for RT::IR::ConstituencyManager

diff --git a/bin/add_constituency.in b/bin/add_constituency.in
index bbcf80f..19a5aa4 100755
--- a/bin/add_constituency.in
+++ b/bin/add_constituency.in
@@ -112,6 +112,8 @@ use RT;
 RT::LoadConfig;
 RT::Init;
 
+my $manager = RT::IR::ConstituencyManager->new;
+
 my %opt;
 
 sub debug {
diff --git a/lib/RT/IR.pm b/lib/RT/IR.pm
index c03f5cf..436f00d 100644
--- a/lib/RT/IR.pm
+++ b/lib/RT/IR.pm
@@ -62,6 +62,7 @@ use Scalar::Util qw(blessed);
 
 use RT::IR::Config;
 use RT::IR::Web;
+use RT::IR::ConstituencyManager;
 RT::IR::Config::Init();
 
 
diff --git a/lib/RT/IR/ConstituencyManager.pm b/lib/RT/IR/ConstituencyManager.pm
new file mode 100644
index 0000000..dfa21ca
--- /dev/null
+++ b/lib/RT/IR/ConstituencyManager.pm
@@ -0,0 +1,70 @@
+# BEGIN BPS TAGGED BLOCK {{{
+#
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2016 Best Practical Solutions, LLC
+#                                          <sales at bestpractical.com>
+#
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
+#
+# This work is made available to you under the terms of Version 2 of
+# the GNU General Public License. A copy of that license should have
+# been provided with this software, but in any event can be snarfed
+# from www.gnu.org.
+#
+# This work is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
+#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
+#
+# END BPS TAGGED BLOCK }}}
+
+package RT::IR::ConstituencyManager;
+use strict;
+use warnings;
+
+sub new {
+    my $proto = shift;
+    my $class = ref($proto) || $proto;
+    my $self  = {};
+    bless( $self, $class );
+    $self->_Init(@_);
+    return $self;
+}
+
+sub _Init {
+    my $self = shift;
+    my %args = (
+        @_,
+    );
+}
+
+1;
+

commit 827f6f995c9673931359ff66d12ba8431ceb0fd4
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Wed May 25 18:54:30 2016 +0000

    Migrate the update logic out of add_constituency into ConstituencyManager

diff --git a/bin/add_constituency.in b/bin/add_constituency.in
index 19a5aa4..313d0a8 100755
--- a/bin/add_constituency.in
+++ b/bin/add_constituency.in
@@ -112,8 +112,6 @@ use RT;
 RT::LoadConfig;
 RT::Init;
 
-my $manager = RT::IR::ConstituencyManager->new;
-
 my %opt;
 
 sub debug {
@@ -136,7 +134,9 @@ if ( $opt{'help'} ) {
     );
 }
 
-my $constituency = sanitize_value( $opt{'name'} );
+my $manager = RT::IR::ConstituencyManager->new(Constituency => $opt{name});
+
+my $constituency = $manager->Constituency;
 unless ( defined $constituency && length $constituency ) {
     require Pod::Usage;
     import Pod::Usage;
@@ -146,459 +146,70 @@ unless ( defined $constituency && length $constituency ) {
     );
 }
 
-my @lifecycles = RT::IR->Lifecycles;
-
-my @queue_prefixes = map { RT::IR::FriendlyLifecycle($_) } @lifecycles;
-
-if ( exists $opt{'rename'} ) {
-    exit rename_value( $constituency => sanitize_value( $opt{'rename'} ) );
+if (exists $opt{'rename'}) {
+    exit rename_constituency($opt{'rename'});
 }
-
-$RT::Handle->BeginTransaction;
-
-my $whois_cf = RT::CustomField->new( RT->SystemUser );
-$whois_cf->LoadByName(
-    Name       => 'RTIR default WHOIS server',
-    LookupType => 'RT::Queue'
-);
-die "Couldn't find 'RTIR default WHOIS server' custom field"
-    unless ( $whois_cf->id );
-
-my $exist = cf_value_exists($constituency);
-
-debug "\nIf you continue then we'll...\n";
-if ($exist) {
-    debug "* WARNING: skip adding constituency value, already exists.\n";
-} else {
-    debug "* add new constituency value: '$constituency'.\n";
+else {
+    exit add_constituency();
 }
 
-foreach my $lifecycle (@lifecycles) {
-    my $prefix = RT::IR::FriendlyLifecycle($lifecycle);
-    debug "* create queue '$prefix - $constituency' if it doesn't exist\n";
-}
-debug <<END;
-* create group 'DutyTeam $constituency' if it don't exist
-* create group 'ReadOnly $constituency' if it don't exist
-* grant basic set of rights to the groups on the queues
+sub add_constituency {
+    $RT::Handle->BeginTransaction;
 
-END
+    my $exist = $manager->cf_value_exists($constituency);
 
-unless ( $opt{'force'} ) {
+    debug "\nIf you continue then we'll...\n";
     if ($exist) {
-        exit 0 unless prompt_yN("Do you want to proceed with update?");
-    } else {
-        exit 0
-            unless prompt_yN(
-            "Do you want to proceed creating the new constituency?");
-    }
-}
-
-debug "Adding constituency $constituency\n";
-my $constituency_cf = add_cf_value($constituency);
-
-my %queues;
-
-# Create our four new queues
-foreach my $lifecycle (@lifecycles) {
-    $queues{$lifecycle}
-        = create_or_load_queue(
-        RT::IR::FriendlyLifecycle($lifecycle) . " - " . $constituency,
-        $lifecycle, $constituency_cf );
-}
-
-# Create a DutyTeam $constituency
-my $dutyteam = create_or_load_group( 'DutyTeam ' . $constituency );
-my $ro       = create_or_load_group( 'ReadOnly ' . $constituency );
-
-my @RO_QUEUE_RIGHTS = (
-    'ShowTicket',
-    'ShowTicketComments',
-    'Watch',
-    'SeeQueue',
-    'ShowTemplate',
-
-);
-
-my @DUTYTEAM_CF_RIGHTS = ( 'SeeCustomField', 'ModifyCustomField' );
-my @RO_CF_RIGHTS = ('SeeCustomField');
-
-# Grant that new dutyteam rights to see and update the CFs
-grant_group_cf_rights( $dutyteam, @DUTYTEAM_CF_RIGHTS );
-
-# Grant that new dutyteam all the regular dutyteam rights for the new constituency queues
-grant_group_queue_rights( $dutyteam, \%queues,
-    RT::IR->DutyTeamAllQueueRights );
-
-# Create or load the group "ReadOnly $constituency"
-grant_group_cf_rights( $ro, @RO_CF_RIGHTS );
-
-# Grant the new readonly group the rights to see the RTIR queues
-grant_group_queue_rights( $ro, \%queues, @RO_QUEUE_RIGHTS );
-
-grant_role_queue_rights( \%queues );
-
-$RT::Handle->Commit;
-
-debug "Done. Enjoy your new constituency.\n";
-
-sub prompt_yN {
-    my $text = shift;
-    print "$text [y/N] ";
-    return 0 unless <STDIN> =~ /^(?:y|yes)$/i;
-    return 1;
-}
-
-sub get_constituency_cf {
-    my $cf = RT::CustomField->new($RT::SystemUser);
-    $cf->Load( "RTIR Constituency", LookupType => 'RT::Queue' );
-    unless ( $cf->id ) {
-        die "Couldn't load the constituency custom field";
-    }
-    return $cf;
-}
-
-sub cf_value_exists {
-    my $value = shift;
-
-    debug "Check that constituency '$value' exists\n";
-
-    my $cf     = get_constituency_cf();
-    my $values = $cf->Values;
-    $values->Limit( FIELD => 'Name', VALUE => $value );
-    my $value_obj = $values->First;
-    if   ( $value_obj && $value_obj->id ) { return $value_obj }
-    else                                  { return undef; }
-}
-
-sub add_cf_value {
-    my $value = shift;
-
-    debug "Adding the value to the constituency CF\n";
-
-    my $cf = get_constituency_cf();
-    if ( cf_value_exists($value) ) {
-        debug "Value '$value' already exists\n";
+        debug "* WARNING: skip adding constituency value, already exists.\n";
     } else {
-        my ( $val, $msg ) = $cf->AddValue( Name => $value );
-        die $msg unless $val;
-        debug "Added '$value' to the constituency field\n";
+        debug "* add new constituency value: '$constituency'.\n";
     }
-    return $cf;
-}
 
-sub grant_role_queue_rights {
-    my $queues = shift;
-    my $everyone = RT::Group->new( RT->SystemUser );
-    $everyone->LoadSystemInternalGroup('Everyone');
-    foreach my $queue ( values %$queues ) {
-        debug "Granting role rights to Everyone for queue " . $queue->Name . "\n";
-        my @rights;
-
-        if ( $queue->Lifecycle eq 'incident_reports' ) {
-            @rights = RT::IR->EveryoneIncidentReportRights();
-        } elsif ( $queue->Lifecycle eq 'incidents' ) {
-            @rights = RT::IR->EveryoneIncidentRights();
-
-        }
-        if ( $queue->Lifecycle eq 'investigations' ) {
-            @rights = RT::IR->EveryoneInvestigationRights();
-
-        } elsif ( $queue->Lifecycle eq 'countermeaures' ) {
-            @rights = RT::IR->EveryoneBlockRights();
-        }
-        # grant 'everyone' rights
-        for my $right (@rights) {
-            debug "\t$right...";
-            
-            if ( $everyone->PrincipalObj->HasRight(
-                Object => $queue,
-                Right  => $right)) {
-            debug "skipping, already granted\n";
-            } else { 
-            my ( $val, $msg ) = $everyone->PrincipalObj->GrantRight(
-                Object => $queue,
-                Right  => $right
-            );
-            if ( !$val ) { die $msg }
-            debug  "done\n";
-        }
-        }
-
-        # grant 'owner' rights
-        debug "\tGranting role rights to Owners on " . $queue->Name . "\n";
-        for my $right ( RT::IR->OwnerAllQueueRights ) {
-            debug "\t$right...";
-            my $owner = $queue->RoleGroup('Owner');
-            if( $owner->PrincipalObj->HasRight(
-                Object => $queue,
-                Right  => $right
-            )) {
-            debug "skipping, already granted\n";
-            } else { 
-            my ( $val, $msg ) = $owner->PrincipalObj->GrantRight(
-                Object => $queue,
-                Right  => $right
-            );
-
-            if ( !$val ) { die $msg }
-            debug  "done\n";
-        }
-        }
+    foreach my $name ($manager->queue_names) {
+        debug "* create queue '$name' if it doesn't exist\n";
     }
-}
+    debug <<END;
+* create group 'DutyTeam $constituency' if it don't exist
+* create group 'ReadOnly $constituency' if it don't exist
+* grant basic set of rights to the groups on the queues
 
-sub grant_group_queue_rights {
-    my $group  = shift;
-    my $queues = shift;
-    my @rights = (@_);
-
-    foreach my $queue ( values %$queues ) {
-        debug "Granting rights for queue "
-            . $queue->Name
-            . " to group "
-            . $group->Name . "\n";
-        foreach my $right (@rights) {
-            debug "\t$right";
-            if ($group->PrincipalObj->HasRight(
-                    Right  => $right,
-                    Object => $queue
-                )
-               )
-            {
-                debug "\t...skipped, already granted\n";
-                next;
-            }
-            my ( $val, $msg ) = $group->PrincipalObj->GrantRight(
-                Right  => $right,
-                Object => $queue
-            );
-            if ($val) {
-                debug "\t...done.\n";
-            } else {
-                die "Failed to grant $right to "
-                    . $group->Name
-                    . " for Queue "
-                    . $queue->Name;
-            }
-        }
-    }
-    return 1;
-}
+END
 
-sub grant_group_single_cf_rights {
-    my ( $cf, $group, $rights_ref ) = @_;
-    my @rights = @$rights_ref;
-
-    debug "Granting rights for custom field "
-        . $cf->Name
-        . " to group "
-        . $group->Name . "\n";
-
-    foreach my $right (@rights) {
-        debug "\t$right";
-        if ($group->PrincipalObj->HasRight(
-                Right  => $right,
-                Object => $cf
-            )
-           )
-        {
-            debug "\t...skipped, already granted\n";
-            next;
-        }
-        my ( $val, $msg ) = $group->PrincipalObj->GrantRight(
-            Right  => $right,
-            Object => $cf
-        );
-        if ($val) {
-            debug "\t...done.\n";
+    unless ( $opt{'force'} ) {
+        if ($exist) {
+            exit 0 unless prompt_yN("Do you want to proceed with update?");
         } else {
-            die "Failed to grant $right to "
-                . $group->Name
-                . " for Custom Field "
-                . $cf->Name
-                . ".\nError: $msg";
-        }
-    }
-}
-
-# XXX TODO this should be looking at cfs on the new queues
-sub grant_group_cf_rights {
-    my $group  = shift;
-    my @rights = (@_);
-
-    my $cfs = RT::CustomFields->new($RT::SystemUser);
-    for my $queue (@queue_prefixes) {
-        my $q = load_queue($queue);
-        $cfs->LimitToObjectId( $q->Id );
-    }
-
-    while ( my $cf = $cfs->Next ) {
-        grant_group_single_cf_rights( $cf, $group, \@rights );
-    }
-
-    # explicitly grant rights on 'RTIR Constituency' cf as well
-    my $rtir_constituency_cf = get_constituency_cf();
-    grant_group_single_cf_rights( $rtir_constituency_cf, $group, \@rights );
-
-    return 1;
-}
-
-sub group_exists {
-    my $name  = shift;
-    my $group = RT::Group->new($RT::SystemUser);
-    $group->LoadByCols( Name => $name );
-    return $group && $group->id ? $group : undef;
-}
-
-sub create_or_load_group {
-    my $name  = shift;
-    my $group = RT::Group->new($RT::SystemUser);
-    $group->LoadUserDefinedGroup($name);
-    unless ( $group->id ) {
-        my ( $val, $msg ) = $group->CreateUserDefinedGroup( Name => $name );
-        debug "Creating new group $name: $msg\n";
-    } else {
-        debug "Group '$name' already exists\n";
-    }
-
-    die "Failed to create group $name." unless $group->id;
-
-    return $group;
-}
-
-sub queue_exists {
-    my $name  = shift;
-    my $queue = RT::Queue->new($RT::SystemUser);
-    $queue->LoadByCols( Name => $name );
-    return $queue && $queue->id ? $queue : undef;
-}
-
-sub load_queue {
-    my $name  = shift;
-    my $queue = queue_exists($name);
-    die "Couldn't load queue '$name'" unless $queue;
-    return $queue;
-}
-
-sub create_or_load_queue {
-    my $name            = shift;
-    my $lifecycle       = shift;
-    my $constituency_cf = shift;
-
-    my $basequeue = RT::Queue->new( RT->SystemUser );
-
-    $basequeue->LoadByCols( Name => RT::IR::FriendlyLifecycle($lifecycle) );
-
-    my $queue = RT::Queue->new($RT::SystemUser);
-    $queue->LoadByCols( Name => $name );
-    unless ( $queue->id ) {
-        my ( $val, $msg ) = $queue->Create(
-            Name              => $name,
-            CommentAddress    => $opt{'comment'},
-            CorrespondAddress => $opt{'correspond'},
-            Lifecycle         => $lifecycle,
-            SLADisabled       => $basequeue->SLADisabled,
-        );
-        debug "Creating new queue '$name': $msg\n";
-        debug "\tcomment address:\t$opt{'comment'}" if $opt{'comment'};
-        debug "\tcorrespond address:\t$opt{'correspond'}"
-            if $opt{'correspond'};
-    } else {
-        debug "Queue '$name' already exists\n";
-        foreach my $type (qw(Comment Correspond)) {
-            next unless $opt{ lc $type };
-            my $method  = $type . 'Address';
-            my $current = $queue->$method();
-            next if $current eq $opt{ lc $type };
-
-            $method = 'Set' . $method;
-            my ( $status, $msg ) = $queue->$method( $opt{ lc $type } );
-            unless ($status) {
-                print STDERR "Couldn't set $type address of '$name' queue\n";
-            } else {
-                debug "\tnew $type address: " . $opt{ lc $type };
-            }
+            exit 0
+                unless prompt_yN(
+                "Do you want to proceed creating the new constituency?");
         }
-        if ( $queue->SLADisabled != $basequeue->SLADisabled ) {
-            my ( $status, $msg ) = $queue->SetSLADisabled( $basequeue->SLADisabled );
-            if ($status) {
-                debug "\tSLADisabled: " . $queue->SLADisabled;
-            }
-            else {
-                print STDERR "Couldn't set SLADisabled of '$name' queue: $msg\n";
-            }
-        }
-    }
-
-    my $basecfs = RT::CustomFields->new( RT->SystemUser );
-    $basecfs->SetContextObject($basequeue);
-    $basecfs->LimitToObjectId( $basequeue->id );
-    $basecfs->LimitToLookupType('RT::Queue-RT::Ticket');
-
-    while ( my $basecf = $basecfs->Next ) {
-        debug "Adding Ticket CustomField "
-            . $basecf->Name
-            . " to queue "
-            . $queue->Name . "\n";
-        $basecf->AddToObject($queue);
-    }
-
-    my $base_txncfs = RT::CustomFields->new( RT->SystemUser );
-    $base_txncfs->SetContextObject($basequeue);
-    $base_txncfs->LimitToObjectId( $basequeue->id );
-    $base_txncfs->LimitToLookupType('RT::Queue-RT::Ticket-RT::Transaction');
-
-    while ( my $base_txncf = $base_txncfs->Next ) {
-        debug "Adding Ticket Transaction CustomField "
-            . $base_txncf->Name
-            . " to queue "
-            . $queue->Name . "\n";
-        $base_txncf->AddToObject($queue);
     }
 
-    $constituency_cf->AddToObject($queue);
-    $queue->AddCustomFieldValue(
-        Field => $constituency_cf->id,
-        Value => $constituency
+    my ($ok) = $manager->add_constituency(
+        Correspond => $opt{correspond},
+        Comment    => $opt{comment},
     );
-    $whois_cf->AddToObject($queue);
-
-    my $templates = RT::Templates->new( RT->SystemUser );
-    $templates->LimitToQueue( $basequeue->id );
-    while ( my $template = $templates->Next ) {
-        my $new_template = RT::Template->new( RT->SystemUser );
-        $new_template->Create(
-            Queue => $queue->id,
-            map { $_ => $template->$_ } qw/Name Description Type Content /,
-        );
-    }
 
-    my $scrips = RT::Scrips->new( RT->SystemUser );
-    $scrips->LimitToQueue( $basequeue->id );
-    while ( my $scrip = $scrips->Next ) {
-        unless ( $scrip->IsAdded( $queue->id ) ) {
-            $scrip->AddToObject( $queue->id );
-        }
+    if ($ok) {
+        $RT::Handle->Commit;
+        debug "Done. Enjoy your new constituency.\n";
+        return 0;
+    }
+    else {
+        $RT::Handle->Rollback;
+        debug "An error occurred; constituency not created.\n";
+        return 1;
     }
-
-    die "Failed to create queue $name." unless $queue->id;
-
-    return $queue;
 }
 
-sub rename_value {
-    my $old = shift;
-    my $new = shift;
-
-    my $value_obj;
+sub rename_constituency {
+    my $new = $manager->sanitize_value(shift);
+    my $old = $manager->Constituency;
 
-    my $constituency_cf = get_constituency_cf();
-
-    unless ( $value_obj = cf_value_exists($old) ) {
+    unless ( $manager->cf_value_exists($old) ) {
         die "Couldn't rename. Constituency '$old' doesn't exist.";
     }
-    if ( cf_value_exists($new) ) {
+    if ( $manager->cf_value_exists($new) ) {
         die "Couldn't rename. Constituency '$new' already exists.";
     }
 
@@ -606,6 +217,7 @@ sub rename_value {
 
     debug "\nIf you continue then we'll...\n";
     debug "* rename constituency value '$old' into '$new'.\n";
+
     my $queues = RT::Queues->new( RT->SystemUser );
     $queues->UnLimit;
     while ( my $queue = $queues->Next ) {
@@ -620,71 +232,32 @@ sub rename_value {
         debug "* rename queue '$oldname' to '$newname'.\n";
     }
 
-    foreach my $basename (@queue_prefixes) {
-    }
     debug <<END;
 * rename group 'DutyTeam $old' if it exists into 'DutyTeam $new'
 * rename group 'ReadOnly $old' if it exists into 'ReadOnly $new'
 
 END
+
     return 0 unless prompt_yN("Do you want to proceed?");
 
-    {
-        my ( $status, $msg ) = $value_obj->SetName($new);
-        die $msg unless $status;
-        debug "Renamed constituency value '$old' -> '$new'.\n";
-    }
+    my ($ok) = $manager->rename_constituency($new);
 
-    $queues = RT::Queues->new( RT->SystemUser );
-    $queues->UnLimit;
-    while ( my $queue = $queues->Next ) {
-        next
-            unless (
-            ( $queue->FirstCustomFieldValue('RTIR Constituency') || '' ) eq
-            $old );
-        my $oldname = $queue->Name;
-        my $newname = $oldname;
-        $newname =~ s/$old/$new/;
-        $queue->AddCustomFieldValue(
-            Field => $constituency_cf->id,
-            Value => $new
-        );
-        my ( $status, $msg ) = $queue->SetName($newname);
-        die $msg unless $status;
-
-        debug "Renamed queue '$oldname' -> '$newname'\n";
+    if ($ok) {
+        $RT::Handle->Commit;
+        debug "Renamed constituency '$old' to '$new'.\n";
+        return 0;
     }
-
-    foreach my $basename (qw(DutyTeam Readonly)) {
-        my $group = group_exists("$basename $old");
-        unless ($group) {
-            debug "Group '$basename $old' doesn't exist. Skipping...\n";
-            next;
-        }
-        if ( group_exists("$basename $new") ) {
-            die
-                "Couldn't rename group, target '$basename $new' already exists.";
-        }
-
-        my ( $status, $msg ) = $group->SetName("$basename $new");
-        die $msg unless $status;
-
-        debug "Renamed group '$basename $old' -> '$basename $new'\n";
+    else {
+        $RT::Handle->Rollback;
+        debug "An error occurred; constituency not renamed.\n";
+        return 1;
     }
-
-    $RT::Handle->Commit;
-
-    return 0;
 }
 
-sub sanitize_value {
-    my $value = shift;
-
-    # cleanup value
-    $value = '' unless defined $value;
-    $value =~ s/^\s+//;
-    $value =~ s/\s+$//;
-    $value =~ s/\s+/ /gs;
-    return $value;
+sub prompt_yN {
+    my $text = shift;
+    print "$text [y/N] ";
+    return 0 unless <STDIN> =~ /^(?:y|yes)$/i;
+    return 1;
 }
 
diff --git a/lib/RT/IR/ConstituencyManager.pm b/lib/RT/IR/ConstituencyManager.pm
index dfa21ca..0cc142a 100644
--- a/lib/RT/IR/ConstituencyManager.pm
+++ b/lib/RT/IR/ConstituencyManager.pm
@@ -50,6 +50,17 @@ package RT::IR::ConstituencyManager;
 use strict;
 use warnings;
 
+our @RO_QUEUE_RIGHTS = (
+    'ShowTicket',
+    'ShowTicketComments',
+    'Watch',
+    'SeeQueue',
+    'ShowTemplate',
+);
+
+our @DUTYTEAM_CF_RIGHTS = ( 'SeeCustomField', 'ModifyCustomField' );
+our @RO_CF_RIGHTS = ('SeeCustomField');
+
 sub new {
     my $proto = shift;
     my $class = ref($proto) || $proto;
@@ -62,8 +73,527 @@ sub new {
 sub _Init {
     my $self = shift;
     my %args = (
+        Constituency => undef,
+        @_,
+    );
+
+    $self->{Constituency} = $self->sanitize_value($args{Constituency});
+}
+
+sub Constituency {
+    my $self = shift;
+    return $self->{Constituency};
+}
+
+sub queue_prefixes {
+    return map { RT::IR::FriendlyLifecycle($_) } RT::IR->Lifecycles;
+}
+
+sub queue_names {
+    my $self = shift;
+    my $constituency = $self->Constituency;
+
+    return map { "$_ - $constituency" } $self->queue_prefixes;
+}
+
+sub get_whois_cf {
+    my $self = shift;
+
+    my $whois_cf = RT::CustomField->new( RT->SystemUser );
+    $whois_cf->LoadByName(
+        Name       => 'RTIR default WHOIS server',
+        LookupType => 'RT::Queue'
+    );
+    die "Couldn't find 'RTIR default WHOIS server' custom field"
+        unless ( $whois_cf->id );
+
+    return $whois_cf;
+}
+
+sub get_constituency_cf {
+    my $self = shift;
+    my $cf = RT::CustomField->new($RT::SystemUser);
+    $cf->Load( "RTIR Constituency", LookupType => 'RT::Queue' );
+    unless ( $cf->id ) {
+        die "Couldn't load the constituency custom field";
+    }
+    return $cf;
+}
+
+sub cf_value_exists {
+    my $self = shift;
+    my $value = shift;
+
+    RT->Logger->debug("Check that constituency '$value' exists");
+
+    my $cf     = $self->get_constituency_cf();
+    my $values = $cf->Values;
+    $values->Limit( FIELD => 'Name', VALUE => $value );
+    my $value_obj = $values->First;
+    if   ( $value_obj && $value_obj->id ) { return $value_obj }
+    else                                  { return undef; }
+}
+
+sub add_cf_value {
+    my $self = shift;
+    my $value = shift;
+
+    RT->Logger->debug("Adding the value to the constituency CF");
+
+    my $cf = $self->get_constituency_cf();
+    if ( $self->cf_value_exists($value) ) {
+        RT->Logger->debug("Value '$value' already exists");
+    } else {
+        my ( $val, $msg ) = $cf->AddValue( Name => $value );
+        die $msg unless $val;
+        RT->Logger->info("Added '$value' to the constituency field");
+    }
+    return $cf;
+}
+
+sub create_or_load_queue {
+    my $self = shift;
+    my %args = (
+        Name       => undef,
+        Lifecycle  => undef,
+        Correspond => undef,
+        Comment    => undef,
+        @_,
+    );
+    my $name = $args{Name};
+
+    my $basequeue = RT::Queue->new( RT->SystemUser );
+
+    $basequeue->LoadByCols( Name => RT::IR::FriendlyLifecycle($args{Lifecycle}) );
+
+    my $queue = RT::Queue->new($RT::SystemUser);
+    $queue->LoadByCols( Name => $name );
+    unless ( $queue->id ) {
+        my ( $val, $msg ) = $queue->Create(
+            Name              => $name,
+            CommentAddress    => $args{Comment},
+            CorrespondAddress => $args{Correspond},
+            Lifecycle         => $args{Lifecycle},
+            SLADisabled       => $basequeue->SLADisabled,
+        );
+        RT->Logger->info("Created new queue '$name': $msg");
+        RT->Logger->debug("Comment address: $args{Comment}") if $args{Comment};
+        RT->Logger->debug("Correspond address: $args{Correspond}")
+            if $args{Correspond};
+    } else {
+        RT->Logger->debug("Queue '$name' already exists");
+        foreach my $type (qw(Comment Correspond)) {
+            next unless $args{$type};
+            my $method  = $type . 'Address';
+            my $current = $queue->$method();
+            next if $current eq $args{$type};
+
+            $method = 'Set' . $method;
+            my ( $status, $msg ) = $queue->$method( $args{$type} );
+            unless ($status) {
+                RT->Logger->error("Couldn't set $type address of '$name' queue");
+            } else {
+                RT->Logger->debug("new $type address: " . $args{$type});
+            }
+        }
+        if ( $queue->SLADisabled != $basequeue->SLADisabled ) {
+            my ( $status, $msg ) = $queue->SetSLADisabled( $basequeue->SLADisabled );
+            if ($status) {
+                RT->Logger->debug("SLADisabled: " . $queue->SLADisabled);
+            }
+            else {
+                RT->Logger->error("Couldn't set SLADisabled of '$name' queue: $msg");
+            }
+        }
+    }
+
+    my $basecfs = RT::CustomFields->new( RT->SystemUser );
+    $basecfs->SetContextObject($basequeue);
+    $basecfs->LimitToObjectId( $basequeue->id );
+    $basecfs->LimitToLookupType('RT::Queue-RT::Ticket');
+
+    while ( my $basecf = $basecfs->Next ) {
+        RT->Logger->debug("Adding Ticket CustomField "
+            . $basecf->Name
+            . " to queue "
+            . $queue->Name);
+        $basecf->AddToObject($queue);
+    }
+
+    my $base_txncfs = RT::CustomFields->new( RT->SystemUser );
+    $base_txncfs->SetContextObject($basequeue);
+    $base_txncfs->LimitToObjectId( $basequeue->id );
+    $base_txncfs->LimitToLookupType('RT::Queue-RT::Ticket-RT::Transaction');
+
+    while ( my $base_txncf = $base_txncfs->Next ) {
+        RT->Logger->debug("Adding Ticket Transaction CustomField "
+            . $base_txncf->Name
+            . " to queue "
+            . $queue->Name);
+        $base_txncf->AddToObject($queue);
+    }
+
+    my $constituency_cf = $self->get_constituency_cf;
+    $constituency_cf->AddToObject($queue);
+    $queue->AddCustomFieldValue(
+        Field => $constituency_cf->id,
+        Value => $self->Constituency,
+    );
+
+    my $whois_cf = $self->get_whois_cf;
+    $whois_cf->AddToObject($queue);
+
+    my $templates = RT::Templates->new( RT->SystemUser );
+    $templates->LimitToQueue( $basequeue->id );
+    while ( my $template = $templates->Next ) {
+        my $new_template = RT::Template->new( RT->SystemUser );
+        $new_template->Create(
+            Queue => $queue->id,
+            map { $_ => $template->$_ } qw/Name Description Type Content /,
+        );
+    }
+
+    my $scrips = RT::Scrips->new( RT->SystemUser );
+    $scrips->LimitToQueue( $basequeue->id );
+    while ( my $scrip = $scrips->Next ) {
+        unless ( $scrip->IsAdded( $queue->id ) ) {
+            $scrip->AddToObject( $queue->id );
+        }
+    }
+
+    die "Failed to create queue $name." unless $queue->id;
+
+    return $queue;
+}
+
+sub create_or_load_queues {
+    my $self = shift;
+    my %args = @_;
+
+    my $constituency = $self->Constituency;
+    my %queues;
+
+    foreach my $lifecycle (RT::IR->Lifecycles) {
+        my $name = RT::IR::FriendlyLifecycle($lifecycle) . " - " . $constituency;
+        $queues{$lifecycle} = $self->create_or_load_queue(
+            Name       => $name,
+            Lifecycle  => $lifecycle,
+            %args,
+        );
+    }
+
+    return %queues;
+}
+
+sub create_or_load_group {
+    my $self = shift;
+    my $name = shift;
+    my $group = RT::Group->new($RT::SystemUser);
+    $group->LoadUserDefinedGroup($name);
+    unless ( $group->id ) {
+        my ( $val, $msg ) = $group->CreateUserDefinedGroup( Name => $name );
+        RT->Logger->info("Created new group $name: $msg");
+    } else {
+        RT->Logger->debug("Group '$name' already exists");
+    }
+
+    die "Failed to create group $name." unless $group->id;
+
+    return $group;
+}
+
+# XXX TODO this should be looking at cfs on the new queues
+sub grant_group_cf_rights {
+    my $self   = shift;
+    my $group  = shift;
+    my @rights = (@_);
+
+    my $cfs = RT::CustomFields->new($RT::SystemUser);
+    for my $name ($self->queue_prefixes) {
+        my $queue = RT::Queue->new($RT::SystemUser);
+        $queue->LoadByCols( Name => $name );
+        die "Couldn't load queue '$name'" unless $queue && $queue->id;
+
+        $cfs->LimitToObjectId( $queue->Id );
+    }
+
+    while ( my $cf = $cfs->Next ) {
+        $self->grant_group_single_cf_rights( $cf, $group, @rights );
+    }
+
+    # explicitly grant rights on 'RTIR Constituency' cf as well
+    my $rtir_constituency_cf = $self->get_constituency_cf();
+    $self->grant_group_single_cf_rights( $rtir_constituency_cf, $group, @rights );
+
+    RT->Logger->info("Granted rights for custom fields to group " . $group->Name);
+
+    return 1;
+}
+
+sub grant_group_single_cf_rights {
+    my $self   = shift;
+    my $cf     = shift;
+    my $group  = shift;
+    my @rights = @_;
+
+    RT->Logger->debug("Granting rights for custom field "
+        . $cf->Name
+        . " to group "
+        . $group->Name);
+
+    foreach my $right (@rights) {
+        RT->Logger->debug("Granting right $right");
+        if ($group->PrincipalObj->HasRight(
+                Right  => $right,
+                Object => $cf
+            )
+           )
+        {
+            RT->Logger->debug("...skipped, already granted");
+            next;
+        }
+        my ( $val, $msg ) = $group->PrincipalObj->GrantRight(
+            Right  => $right,
+            Object => $cf
+        );
+        if ($val) {
+            RT->Logger->debug("Granted right $right");
+        } else {
+            die "Failed to grant $right to "
+                . $group->Name
+                . " for Custom Field "
+                . $cf->Name
+                . ".\nError: $msg";
+        }
+    }
+}
+
+sub grant_role_queue_rights {
+    my $self   = shift;
+    my $queues = shift;
+
+    my $everyone = RT::Group->new( RT->SystemUser );
+    $everyone->LoadSystemInternalGroup('Everyone');
+
+    foreach my $queue ( values %$queues ) {
+        RT->Logger->debug("Granting role rights to Everyone for queue " . $queue->Name);
+        my @rights;
+
+        if ( $queue->Lifecycle eq 'incident_reports' ) {
+            @rights = RT::IR->EveryoneIncidentReportRights();
+        } elsif ( $queue->Lifecycle eq 'incidents' ) {
+            @rights = RT::IR->EveryoneIncidentRights();
+
+        }
+        if ( $queue->Lifecycle eq 'investigations' ) {
+            @rights = RT::IR->EveryoneInvestigationRights();
+
+        } elsif ( $queue->Lifecycle eq 'countermeaures' ) {
+            @rights = RT::IR->EveryoneBlockRights();
+        }
+        # grant 'everyone' rights
+        for my $right (@rights) {
+            RT->Logger->debug("Granting right $right");
+
+            if ( $everyone->PrincipalObj->HasRight(
+                Object => $queue,
+                Right  => $right)) {
+                RT->Logger->debug("skipping, already granted");
+            } else { 
+            my ( $val, $msg ) = $everyone->PrincipalObj->GrantRight(
+                Object => $queue,
+                Right  => $right
+            );
+            if ( !$val ) { die $msg }
+            RT->Logger->debug("Granted right $right to Everyone for queue " . $queue->Name);
+        }
+        }
+        RT->Logger->info("Granted role rights to Everyone for queue " . $queue->Name);
+
+        # grant 'owner' rights
+        RT->Logger->debug("Granting role rights to Owners on " . $queue->Name);
+        for my $right ( RT::IR->OwnerAllQueueRights ) {
+            RT->Logger->debug("Granting right $right...");
+            my $owner = $queue->RoleGroup('Owner');
+            if( $owner->PrincipalObj->HasRight(
+                Object => $queue,
+                Right  => $right
+            )) {
+                RT->Logger->debug("skipping, already granted");
+            } else { 
+                my ( $val, $msg ) = $owner->PrincipalObj->GrantRight(
+                    Object => $queue,
+                    Right  => $right
+                );
+
+                if ( !$val ) { die $msg }
+                RT->Logger->debug("Granted right $right...");
+            }
+        }
+        RT->Logger->info("Granted role rights to Owners on " . $queue->Name);
+    }
+}
+
+sub grant_group_queue_rights {
+    my $self   = shift;
+    my $group  = shift;
+    my $queues = shift;
+    my @rights = (@_);
+
+    foreach my $queue ( values %$queues ) {
+        RT->Logger->debug("Granting rights for queue "
+            . $queue->Name
+            . " to group "
+            . $group->Name);
+
+        foreach my $right (@rights) {
+            RT->Logger->debug("Granting right $right");
+            if ($group->PrincipalObj->HasRight(
+                    Right  => $right,
+                    Object => $queue
+                )
+               )
+            {
+                RT->Logger->debug("...skipped, already granted");
+                next;
+            }
+            my ( $val, $msg ) = $group->PrincipalObj->GrantRight(
+                Right  => $right,
+                Object => $queue
+            );
+            if ($val) {
+                RT->Logger->debug("Granted right $right for queue "
+                    . $queue->Name
+                    . " to group "
+                    . $group->Name);
+            } else {
+                die "Failed to grant $right to "
+                    . $group->Name
+                    . " for Queue "
+                    . $queue->Name;
+            }
+        }
+    }
+
+    RT->Logger->info("Granted rights for queues to group " . $group->Name);
+
+    return 1;
+}
+
+sub add_constituency {
+    my $self = shift;
+    my %args = (
+        Correspond => undef,
+        Comment    => undef,
         @_,
     );
+
+    my $constituency = $self->Constituency;
+
+    RT->Logger->info("Adding constituency $constituency");
+
+    my $constituency_cf = $self->add_cf_value($constituency);
+
+    # Create our four new queues
+    my %queues = $self->create_or_load_queues(%args);
+
+    # Create a DutyTeam $constituency
+    my $dutyteam = $self->create_or_load_group( 'DutyTeam ' . $constituency );
+    my $ro       = $self->create_or_load_group( 'ReadOnly ' . $constituency );
+
+    # Grant that new dutyteam rights to see and update the CFs
+    $self->grant_group_cf_rights( $dutyteam, @DUTYTEAM_CF_RIGHTS );
+
+    # Grant that new dutyteam all the regular dutyteam rights for the new constituency queues
+    $self->grant_group_queue_rights( $dutyteam, \%queues,
+        RT::IR->DutyTeamAllQueueRights );
+
+    # Create or load the group "ReadOnly $constituency"
+    $self->grant_group_cf_rights( $ro, @RO_CF_RIGHTS );
+
+    # Grant the new readonly group the rights to see the RTIR queues
+    $self->grant_group_queue_rights( $ro, \%queues, @RO_QUEUE_RIGHTS );
+
+    $self->grant_role_queue_rights( \%queues );
+
+    return 1;
+}
+
+sub _group_exists {
+    my $self  = shift;
+    my $name  = shift;
+    my $group = RT::Group->new($RT::SystemUser);
+    $group->LoadByCols( Name => $name );
+    return $group && $group->id ? $group : undef;
+}
+
+sub rename_constituency {
+    my $self = shift;
+    my $new = $self->sanitize_value(shift);
+    my $old = $self->Constituency;
+
+    my $constituency_cf = $self->get_constituency_cf;
+
+    {
+        my $value_obj = $self->cf_value_exists($old);
+        my ( $status, $msg ) = $value_obj->SetName($new);
+        die $msg unless $status;
+        RT->Logger->info("Renamed constituency value '$old' -> '$new'.");
+    }
+
+    my $queues = RT::Queues->new( RT->SystemUser );
+    $queues->UnLimit;
+    while ( my $queue = $queues->Next ) {
+        next
+            unless (
+            ( $queue->FirstCustomFieldValue('RTIR Constituency') || '' ) eq
+            $old );
+        my $oldname = $queue->Name;
+        my $newname = $oldname;
+        $newname =~ s/$old/$new/;
+        $queue->AddCustomFieldValue(
+            Field => $constituency_cf->id,
+            Value => $new
+        );
+        my ( $status, $msg ) = $queue->SetName($newname);
+        die $msg unless $status;
+
+        RT->Logger->info("Renamed queue '$oldname' -> '$newname'");
+    }
+
+    foreach my $basename (qw(DutyTeam Readonly)) {
+        my $old_name = "$basename $old";
+        my $new_name = "$basename $new";
+
+        my $group = $self->_group_exists($old_name);
+        unless ($group) {
+            RT->Logger->debug("Group '$old_name' doesn't exist. Skipping...");
+            next;
+        }
+        if ( $self->_group_exists($new_name) ) {
+            die
+                "Couldn't rename group, target '$new_name' already exists.";
+        }
+
+        my ( $status, $msg ) = $group->SetName($new_name);
+        die $msg unless $status;
+
+        RT->Logger->info("Renamed group '$old_name' -> '$new_name'");
+    }
+
+    return 1;
+}
+
+sub sanitize_value {
+    my $self = shift;
+    my $value = shift;
+
+    # cleanup value
+    $value = '' unless defined $value;
+    $value =~ s/^\s+//;
+    $value =~ s/\s+$//;
+    $value =~ s/\s+/ /gs;
+    return $value;
 }
 
 1;

commit d8abc5102a7c3db185633147545f62f656020831
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Wed May 25 18:22:49 2016 +0000

    Factor out a ->queues method doing the CF search in SQL

diff --git a/bin/add_constituency.in b/bin/add_constituency.in
index 313d0a8..3678c53 100755
--- a/bin/add_constituency.in
+++ b/bin/add_constituency.in
@@ -218,13 +218,8 @@ sub rename_constituency {
     debug "\nIf you continue then we'll...\n";
     debug "* rename constituency value '$old' into '$new'.\n";
 
-    my $queues = RT::Queues->new( RT->SystemUser );
-    $queues->UnLimit;
-    while ( my $queue = $queues->Next ) {
-        next
-            unless (
-            ( $queue->FirstCustomFieldValue('RTIR Constituency') || '' ) eq
-            $old );
+    my $queues = $manager->queues;
+    while (my $queue = $queues->Next) {
         my $oldname = $queue->Name;
         my $newname = $oldname;
         $newname =~ s/$old/$new/;
diff --git a/lib/RT/IR/ConstituencyManager.pm b/lib/RT/IR/ConstituencyManager.pm
index 0cc142a..708347c 100644
--- a/lib/RT/IR/ConstituencyManager.pm
+++ b/lib/RT/IR/ConstituencyManager.pm
@@ -96,6 +96,17 @@ sub queue_names {
     return map { "$_ - $constituency" } $self->queue_prefixes;
 }
 
+sub queues {
+    my $self = shift;
+
+    my $queues = RT::Queues->new( RT->SystemUser );
+    $queues->LimitCustomField(
+        CUSTOMFIELD => $self->get_constituency_cf->Id,
+        VALUE       => $self->Constituency,
+    );
+    return $queues;
+}
+
 sub get_whois_cf {
     my $self = shift;
 
@@ -541,20 +552,17 @@ sub rename_constituency {
         RT->Logger->info("Renamed constituency value '$old' -> '$new'.");
     }
 
-    my $queues = RT::Queues->new( RT->SystemUser );
-    $queues->UnLimit;
-    while ( my $queue = $queues->Next ) {
-        next
-            unless (
-            ( $queue->FirstCustomFieldValue('RTIR Constituency') || '' ) eq
-            $old );
-        my $oldname = $queue->Name;
-        my $newname = $oldname;
-        $newname =~ s/$old/$new/;
+    my $queues = $self->queues;
+    while (my $queue = $queues->Next) {
         $queue->AddCustomFieldValue(
             Field => $constituency_cf->id,
             Value => $new
         );
+
+        my $oldname = $queue->Name;
+        my $newname = $oldname;
+        $newname =~ s/$old/$new/;
+
         my ( $status, $msg ) = $queue->SetName($newname);
         die $msg unless $status;
 

commit 31aededf22d24be960bb204dae6f99b98eef1f85
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Wed May 25 18:27:40 2016 +0000

    Rename debug function to notify
    
        It now has the sole purpose of telling the user what's going to
        happen when they commit to the add/rename action

diff --git a/bin/add_constituency.in b/bin/add_constituency.in
index 3678c53..945f572 100755
--- a/bin/add_constituency.in
+++ b/bin/add_constituency.in
@@ -114,7 +114,7 @@ RT::Init;
 
 my %opt;
 
-sub debug {
+sub notify {
     return if $opt{'quiet'};
     print @_;
     return 1;
@@ -158,17 +158,17 @@ sub add_constituency {
 
     my $exist = $manager->cf_value_exists($constituency);
 
-    debug "\nIf you continue then we'll...\n";
+    notify "\nIf you continue then we'll...\n";
     if ($exist) {
-        debug "* WARNING: skip adding constituency value, already exists.\n";
+        notify "* WARNING: skip adding constituency value, already exists.\n";
     } else {
-        debug "* add new constituency value: '$constituency'.\n";
+        notify "* add new constituency value: '$constituency'.\n";
     }
 
     foreach my $name ($manager->queue_names) {
-        debug "* create queue '$name' if it doesn't exist\n";
+        notify "* create queue '$name' if it doesn't exist\n";
     }
-    debug <<END;
+    notify <<END;
 * create group 'DutyTeam $constituency' if it don't exist
 * create group 'ReadOnly $constituency' if it don't exist
 * grant basic set of rights to the groups on the queues
@@ -192,12 +192,12 @@ END
 
     if ($ok) {
         $RT::Handle->Commit;
-        debug "Done. Enjoy your new constituency.\n";
+        notify "Done. Enjoy your new constituency.\n";
         return 0;
     }
     else {
         $RT::Handle->Rollback;
-        debug "An error occurred; constituency not created.\n";
+        notify "An error occurred; constituency not created.\n";
         return 1;
     }
 }
@@ -215,8 +215,8 @@ sub rename_constituency {
 
     $RT::Handle->BeginTransaction;
 
-    debug "\nIf you continue then we'll...\n";
-    debug "* rename constituency value '$old' into '$new'.\n";
+    notify "\nIf you continue then we'll...\n";
+    notify "* rename constituency value '$old' into '$new'.\n";
 
     my $queues = $manager->queues;
     while (my $queue = $queues->Next) {
@@ -224,10 +224,10 @@ sub rename_constituency {
         my $newname = $oldname;
         $newname =~ s/$old/$new/;
 
-        debug "* rename queue '$oldname' to '$newname'.\n";
+        notify "* rename queue '$oldname' to '$newname'.\n";
     }
 
-    debug <<END;
+    notify <<END;
 * rename group 'DutyTeam $old' if it exists into 'DutyTeam $new'
 * rename group 'ReadOnly $old' if it exists into 'ReadOnly $new'
 
@@ -239,12 +239,12 @@ END
 
     if ($ok) {
         $RT::Handle->Commit;
-        debug "Renamed constituency '$old' to '$new'.\n";
+        notify "Renamed constituency '$old' to '$new'.\n";
         return 0;
     }
     else {
         $RT::Handle->Rollback;
-        debug "An error occurred; constituency not renamed.\n";
+        notify "An error occurred; constituency not renamed.\n";
         return 1;
     }
 }

commit d51f9dc4c5d68b7d7ca86ec0197661bd6c0a9200
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Wed May 25 18:54:50 2016 +0000

    Have --quiet and new --verbose options manage output log level

diff --git a/bin/add_constituency.in b/bin/add_constituency.in
index 945f572..269ac0d 100755
--- a/bin/add_constituency.in
+++ b/bin/add_constituency.in
@@ -57,9 +57,9 @@ add_constituency - add or update constitiuensies
     add_constituency --help
     add_constituency --name <constituency> [options]
     add_constituency --name EDUNET
-    add_constituency --name EDUNET --correspond 'edunet at example.com' --quiet
+    add_constituency --name EDUNET --correspond 'edunet at example.com' --verbose
 
-    add_constituency --name <constituency> --rename <new value>
+    add_constituency --name <constituency> --rename <new value> --quiet
 
     add_constituency --name EDUNET --force
 
@@ -85,7 +85,11 @@ Rename constituency, use this option to set new value when --name defines old.
 
 =item --quiet
 
-Disable output.
+Limit output to only errors.
+
+=item --verbose
+
+Additional debugging output.
 
 =item --force
 
@@ -110,7 +114,6 @@ use lib qw(/opt/rt4/local/lib /opt/rt4/lib);
 
 use RT;
 RT::LoadConfig;
-RT::Init;
 
 my %opt;
 
@@ -122,7 +125,7 @@ sub notify {
 
 use Getopt::Long;
 GetOptions( \%opt, "name=s", "rename=s", "correspond=s", "comment=s", "help",
-    "quiet", "force" );
+    "quiet", "verbose", "force" );
 
 if ( $opt{'help'} ) {
     require Pod::Usage;
@@ -134,6 +137,18 @@ if ( $opt{'help'} ) {
     );
 }
 
+if ($opt{verbose}) {
+    RT->Config->Set(LogToSTDERR => 'debug');
+}
+elsif ($opt{quiet}) {
+    RT->Config->Set(LogToSTDERR => 'error');
+}
+else {
+    RT->Config->Set(LogToSTDERR => 'info');
+}
+
+RT::Init;
+
 my $manager = RT::IR::ConstituencyManager->new(Constituency => $opt{name});
 
 my $constituency = $manager->Constituency;

commit 3a0c2f0108ea5c84167ec9486480b70b1de8e87d
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Wed May 25 18:36:03 2016 +0000

    Make prompt messages clearer in add_constituency

diff --git a/bin/add_constituency.in b/bin/add_constituency.in
index 269ac0d..11d3322 100755
--- a/bin/add_constituency.in
+++ b/bin/add_constituency.in
@@ -192,7 +192,7 @@ END
 
     unless ( $opt{'force'} ) {
         if ($exist) {
-            exit 0 unless prompt_yN("Do you want to proceed with update?");
+            exit 0 unless prompt_yN("Do you want to proceed with adding this constituency?");
         } else {
             exit 0
                 unless prompt_yN(
@@ -248,7 +248,7 @@ sub rename_constituency {
 
 END
 
-    return 0 unless prompt_yN("Do you want to proceed?");
+    return 0 unless prompt_yN("Do you want to proceed with renaming this constituency?");
 
     my ($ok) = $manager->rename_constituency($new);
 

commit d62c871da1987d37260476fbee87cd7adae510b0
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Wed May 25 18:45:35 2016 +0000

    Rename ConstituencyManager methods from snake_case to CamelCase

diff --git a/bin/add_constituency.in b/bin/add_constituency.in
index 11d3322..5e3d780 100755
--- a/bin/add_constituency.in
+++ b/bin/add_constituency.in
@@ -171,7 +171,7 @@ else {
 sub add_constituency {
     $RT::Handle->BeginTransaction;
 
-    my $exist = $manager->cf_value_exists($constituency);
+    my $exist = $manager->CustomFieldValueExists($constituency);
 
     notify "\nIf you continue then we'll...\n";
     if ($exist) {
@@ -180,7 +180,7 @@ sub add_constituency {
         notify "* add new constituency value: '$constituency'.\n";
     }
 
-    foreach my $name ($manager->queue_names) {
+    foreach my $name ($manager->QueueNames) {
         notify "* create queue '$name' if it doesn't exist\n";
     }
     notify <<END;
@@ -200,7 +200,7 @@ END
         }
     }
 
-    my ($ok) = $manager->add_constituency(
+    my ($ok) = $manager->AddConstituency(
         Correspond => $opt{correspond},
         Comment    => $opt{comment},
     );
@@ -218,13 +218,13 @@ END
 }
 
 sub rename_constituency {
-    my $new = $manager->sanitize_value(shift);
+    my $new = $manager->SanitizeValue(shift);
     my $old = $manager->Constituency;
 
-    unless ( $manager->cf_value_exists($old) ) {
+    unless ( $manager->CustomFieldValueExists($old) ) {
         die "Couldn't rename. Constituency '$old' doesn't exist.";
     }
-    if ( $manager->cf_value_exists($new) ) {
+    if ( $manager->CustomFieldValueExists($new) ) {
         die "Couldn't rename. Constituency '$new' already exists.";
     }
 
@@ -233,7 +233,7 @@ sub rename_constituency {
     notify "\nIf you continue then we'll...\n";
     notify "* rename constituency value '$old' into '$new'.\n";
 
-    my $queues = $manager->queues;
+    my $queues = $manager->Queues;
     while (my $queue = $queues->Next) {
         my $oldname = $queue->Name;
         my $newname = $oldname;
@@ -250,7 +250,7 @@ END
 
     return 0 unless prompt_yN("Do you want to proceed with renaming this constituency?");
 
-    my ($ok) = $manager->rename_constituency($new);
+    my ($ok) = $manager->RenameConstituency($new);
 
     if ($ok) {
         $RT::Handle->Commit;
diff --git a/lib/RT/IR/ConstituencyManager.pm b/lib/RT/IR/ConstituencyManager.pm
index 708347c..1b5ce73 100644
--- a/lib/RT/IR/ConstituencyManager.pm
+++ b/lib/RT/IR/ConstituencyManager.pm
@@ -77,7 +77,7 @@ sub _Init {
         @_,
     );
 
-    $self->{Constituency} = $self->sanitize_value($args{Constituency});
+    $self->{Constituency} = $self->SanitizeValue($args{Constituency});
 }
 
 sub Constituency {
@@ -85,29 +85,29 @@ sub Constituency {
     return $self->{Constituency};
 }
 
-sub queue_prefixes {
+sub QueuePrefixes {
     return map { RT::IR::FriendlyLifecycle($_) } RT::IR->Lifecycles;
 }
 
-sub queue_names {
+sub QueueNames {
     my $self = shift;
     my $constituency = $self->Constituency;
 
-    return map { "$_ - $constituency" } $self->queue_prefixes;
+    return map { "$_ - $constituency" } $self->QueuePrefixes;
 }
 
-sub queues {
+sub Queues {
     my $self = shift;
 
     my $queues = RT::Queues->new( RT->SystemUser );
     $queues->LimitCustomField(
-        CUSTOMFIELD => $self->get_constituency_cf->Id,
+        CUSTOMFIELD => $self->ConstituencyCustomField->Id,
         VALUE       => $self->Constituency,
     );
     return $queues;
 }
 
-sub get_whois_cf {
+sub WhoisCustomField {
     my $self = shift;
 
     my $whois_cf = RT::CustomField->new( RT->SystemUser );
@@ -121,7 +121,7 @@ sub get_whois_cf {
     return $whois_cf;
 }
 
-sub get_constituency_cf {
+sub ConstituencyCustomField {
     my $self = shift;
     my $cf = RT::CustomField->new($RT::SystemUser);
     $cf->Load( "RTIR Constituency", LookupType => 'RT::Queue' );
@@ -131,13 +131,13 @@ sub get_constituency_cf {
     return $cf;
 }
 
-sub cf_value_exists {
+sub CustomFieldValueExists {
     my $self = shift;
     my $value = shift;
 
     RT->Logger->debug("Check that constituency '$value' exists");
 
-    my $cf     = $self->get_constituency_cf();
+    my $cf     = $self->ConstituencyCustomField;
     my $values = $cf->Values;
     $values->Limit( FIELD => 'Name', VALUE => $value );
     my $value_obj = $values->First;
@@ -145,14 +145,14 @@ sub cf_value_exists {
     else                                  { return undef; }
 }
 
-sub add_cf_value {
+sub AddCustomFieldValue {
     my $self = shift;
     my $value = shift;
 
     RT->Logger->debug("Adding the value to the constituency CF");
 
-    my $cf = $self->get_constituency_cf();
-    if ( $self->cf_value_exists($value) ) {
+    my $cf = $self->ConstituencyCustomField;
+    if ( $self->CustomFieldValueExists($value) ) {
         RT->Logger->debug("Value '$value' already exists");
     } else {
         my ( $val, $msg ) = $cf->AddValue( Name => $value );
@@ -162,7 +162,7 @@ sub add_cf_value {
     return $cf;
 }
 
-sub create_or_load_queue {
+sub CreateOrLoadQueue {
     my $self = shift;
     my %args = (
         Name       => undef,
@@ -244,14 +244,14 @@ sub create_or_load_queue {
         $base_txncf->AddToObject($queue);
     }
 
-    my $constituency_cf = $self->get_constituency_cf;
+    my $constituency_cf = $self->ConstituencyCustomField;
     $constituency_cf->AddToObject($queue);
     $queue->AddCustomFieldValue(
         Field => $constituency_cf->id,
         Value => $self->Constituency,
     );
 
-    my $whois_cf = $self->get_whois_cf;
+    my $whois_cf = $self->WhoisCustomField;
     $whois_cf->AddToObject($queue);
 
     my $templates = RT::Templates->new( RT->SystemUser );
@@ -277,7 +277,7 @@ sub create_or_load_queue {
     return $queue;
 }
 
-sub create_or_load_queues {
+sub CreateOrLoadQueues {
     my $self = shift;
     my %args = @_;
 
@@ -286,7 +286,7 @@ sub create_or_load_queues {
 
     foreach my $lifecycle (RT::IR->Lifecycles) {
         my $name = RT::IR::FriendlyLifecycle($lifecycle) . " - " . $constituency;
-        $queues{$lifecycle} = $self->create_or_load_queue(
+        $queues{$lifecycle} = $self->CreateOrLoadQueue(
             Name       => $name,
             Lifecycle  => $lifecycle,
             %args,
@@ -296,7 +296,7 @@ sub create_or_load_queues {
     return %queues;
 }
 
-sub create_or_load_group {
+sub CreateOrLoadGroup {
     my $self = shift;
     my $name = shift;
     my $group = RT::Group->new($RT::SystemUser);
@@ -314,13 +314,13 @@ sub create_or_load_group {
 }
 
 # XXX TODO this should be looking at cfs on the new queues
-sub grant_group_cf_rights {
+sub GrantGroupCustomFieldRights {
     my $self   = shift;
     my $group  = shift;
     my @rights = (@_);
 
     my $cfs = RT::CustomFields->new($RT::SystemUser);
-    for my $name ($self->queue_prefixes) {
+    for my $name ($self->QueuePrefixes) {
         my $queue = RT::Queue->new($RT::SystemUser);
         $queue->LoadByCols( Name => $name );
         die "Couldn't load queue '$name'" unless $queue && $queue->id;
@@ -329,19 +329,19 @@ sub grant_group_cf_rights {
     }
 
     while ( my $cf = $cfs->Next ) {
-        $self->grant_group_single_cf_rights( $cf, $group, @rights );
+        $self->GrantGroupSingleCustomFieldRights( $cf, $group, @rights );
     }
 
     # explicitly grant rights on 'RTIR Constituency' cf as well
-    my $rtir_constituency_cf = $self->get_constituency_cf();
-    $self->grant_group_single_cf_rights( $rtir_constituency_cf, $group, @rights );
+    my $rtir_constituency_cf = $self->ConstituencyCustomField();
+    $self->GrantGroupSingleCustomFieldRights( $rtir_constituency_cf, $group, @rights );
 
     RT->Logger->info("Granted rights for custom fields to group " . $group->Name);
 
     return 1;
 }
 
-sub grant_group_single_cf_rights {
+sub GrantGroupSingleCustomFieldRights {
     my $self   = shift;
     my $cf     = shift;
     my $group  = shift;
@@ -379,7 +379,7 @@ sub grant_group_single_cf_rights {
     }
 }
 
-sub grant_role_queue_rights {
+sub GrantRoleQueueRights {
     my $self   = shift;
     my $queues = shift;
 
@@ -445,7 +445,7 @@ sub grant_role_queue_rights {
     }
 }
 
-sub grant_group_queue_rights {
+sub GrantGroupQueueRights {
     my $self   = shift;
     my $group  = shift;
     my $queues = shift;
@@ -491,7 +491,7 @@ sub grant_group_queue_rights {
     return 1;
 }
 
-sub add_constituency {
+sub AddConstituency {
     my $self = shift;
     my %args = (
         Correspond => undef,
@@ -503,34 +503,34 @@ sub add_constituency {
 
     RT->Logger->info("Adding constituency $constituency");
 
-    my $constituency_cf = $self->add_cf_value($constituency);
+    my $constituency_cf = $self->AddCustomFieldValue($constituency);
 
     # Create our four new queues
-    my %queues = $self->create_or_load_queues(%args);
+    my %queues = $self->CreateOrLoadQueues(%args);
 
     # Create a DutyTeam $constituency
-    my $dutyteam = $self->create_or_load_group( 'DutyTeam ' . $constituency );
-    my $ro       = $self->create_or_load_group( 'ReadOnly ' . $constituency );
+    my $dutyteam = $self->CreateOrLoadGroup( 'DutyTeam ' . $constituency );
+    my $ro       = $self->CreateOrLoadGroup( 'ReadOnly ' . $constituency );
 
     # Grant that new dutyteam rights to see and update the CFs
-    $self->grant_group_cf_rights( $dutyteam, @DUTYTEAM_CF_RIGHTS );
+    $self->GrantGroupCustomFieldRights( $dutyteam, @DUTYTEAM_CF_RIGHTS );
 
     # Grant that new dutyteam all the regular dutyteam rights for the new constituency queues
-    $self->grant_group_queue_rights( $dutyteam, \%queues,
+    $self->GrantGroupQueueRights( $dutyteam, \%queues,
         RT::IR->DutyTeamAllQueueRights );
 
     # Create or load the group "ReadOnly $constituency"
-    $self->grant_group_cf_rights( $ro, @RO_CF_RIGHTS );
+    $self->GrantGroupCustomFieldRights( $ro, @RO_CF_RIGHTS );
 
     # Grant the new readonly group the rights to see the RTIR queues
-    $self->grant_group_queue_rights( $ro, \%queues, @RO_QUEUE_RIGHTS );
+    $self->GrantGroupQueueRights( $ro, \%queues, @RO_QUEUE_RIGHTS );
 
-    $self->grant_role_queue_rights( \%queues );
+    $self->GrantRoleQueueRights( \%queues );
 
     return 1;
 }
 
-sub _group_exists {
+sub _GroupExists {
     my $self  = shift;
     my $name  = shift;
     my $group = RT::Group->new($RT::SystemUser);
@@ -538,21 +538,21 @@ sub _group_exists {
     return $group && $group->id ? $group : undef;
 }
 
-sub rename_constituency {
+sub RenameConstituency {
     my $self = shift;
-    my $new = $self->sanitize_value(shift);
+    my $new = $self->SanitizeValue(shift);
     my $old = $self->Constituency;
 
-    my $constituency_cf = $self->get_constituency_cf;
+    my $constituency_cf = $self->ConstituencyCustomField;
 
     {
-        my $value_obj = $self->cf_value_exists($old);
+        my $value_obj = $self->CustomFieldValueExists($old);
         my ( $status, $msg ) = $value_obj->SetName($new);
         die $msg unless $status;
         RT->Logger->info("Renamed constituency value '$old' -> '$new'.");
     }
 
-    my $queues = $self->queues;
+    my $queues = $self->Queues;
     while (my $queue = $queues->Next) {
         $queue->AddCustomFieldValue(
             Field => $constituency_cf->id,
@@ -573,12 +573,12 @@ sub rename_constituency {
         my $old_name = "$basename $old";
         my $new_name = "$basename $new";
 
-        my $group = $self->_group_exists($old_name);
+        my $group = $self->_GroupExists($old_name);
         unless ($group) {
             RT->Logger->debug("Group '$old_name' doesn't exist. Skipping...");
             next;
         }
-        if ( $self->_group_exists($new_name) ) {
+        if ( $self->_GroupExists($new_name) ) {
             die
                 "Couldn't rename group, target '$new_name' already exists.";
         }
@@ -592,7 +592,7 @@ sub rename_constituency {
     return 1;
 }
 
-sub sanitize_value {
+sub SanitizeValue {
     my $self = shift;
     my $value = shift;
 

commit fa28f3334dceed1a3d03a798147e7dfd160fdf6f
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Wed May 25 18:52:12 2016 +0000

    Switch test from invoking bin/add_constituency to using RT::IR::ConstituencyManager

diff --git a/t/constituency/basics.t b/t/constituency/basics.t
index 03a5abb..4e43262 100644
--- a/t/constituency/basics.t
+++ b/t/constituency/basics.t
@@ -43,7 +43,8 @@ diag "check that CF applies to all RTIR's queues" if $ENV{'TEST_VERBOSE'};
 diag "create constituencies EDUNET and GOVNET" if $ENV{'TEST_VERBOSE'};
 {
     for my $constituency_name ( qw(EDUNET GOVNET) ) {
-        ok !system("bin/add_constituency --quiet --force --name $constituency_name 2>&1"), "add_constituency $constituency_name ran successfully";
+        my $manager = RT::IR::ConstituencyManager->new(Constituency => $constituency_name);
+        ok($manager->AddConstituency, "added constituency $constituency_name");
     }
 }
 

-----------------------------------------------------------------------


More information about the rt-commit mailing list