[Bps-public-commit] rt-extension-notifysms branch, cleanup-initial-release, created. ae7cb3d28b3bd93492cb2550400ebf5016d3c721

Craig Kaiser craig at bestpractical.com
Mon Jan 25 15:49:55 EST 2021


The branch, cleanup-initial-release has been created
        at  ae7cb3d28b3bd93492cb2550400ebf5016d3c721 (commit)

- Log -----------------------------------------------------------------
commit 65f66fdf11476b429bb01b370b2f9736e17aeace
Author: craig kaiser <craig at bestpractical.com>
Date:   Thu Jan 21 09:57:12 2021 -0500

    Update Module::Install

diff --git a/META.yml b/META.yml
index 261b79f..62d6fca 100644
--- a/META.yml
+++ b/META.yml
@@ -24,6 +24,6 @@ resources:
   license: http://opensource.org/licenses/gpl-license.php
   repository: https://github.com/bestpractical/rt-extension-NotifySMS
 version: '0.01'
-x_module_install_rtx_version: '0.40'
+x_module_install_rtx_version: '0.42'
 x_requires_rt: 4.4.0
-x_rt_too_new: 4.6.0
+x_rt_too_new: 5.1.0
diff --git a/Makefile.PL b/Makefile.PL
index 7913dbf..55822c9 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -5,7 +5,7 @@ license 'gplv2';
 repository 'https://github.com/bestpractical/rt-extension-NotifySMS';
 
 requires_rt '4.4.0';
-rt_too_new '4.6.0';
+rt_too_new '5.1.0';
 
 sign;
 WriteAll;
diff --git a/inc/Module/Install/RTx.pm b/inc/Module/Install/RTx.pm
index 7cad529..2dd9489 100644
--- a/inc/Module/Install/RTx.pm
+++ b/inc/Module/Install/RTx.pm
@@ -6,9 +6,10 @@ use strict;
 use warnings;
 no warnings 'once';
 
+use Term::ANSIColor qw(:constants);
 use Module::Install::Base;
 use base 'Module::Install::Base';
-our $VERSION = '0.40';
+our $VERSION = '0.42';
 
 use FindBin;
 use File::Glob     ();
@@ -53,7 +54,7 @@ sub RTx {
         my @look = @INC;
         unshift @look, grep {defined and -d $_} @try;
         push @look, grep {defined and -d $_}
-            map { ( "$_/rt4/lib", "$_/lib/rt4", "$_/lib" ) } @prefixes;
+            map { ( "$_/rt5/lib", "$_/lib/rt5", "$_/rt4/lib", "$_/lib/rt4", "$_/lib" ) } @prefixes;
         last if eval {local @INC = @look; require RT; $RT::LocalLibPath};
 
         warn
@@ -76,6 +77,22 @@ sub RTx {
         $self->requires_rt('4.0.0');
     }
 
+    my $package = $name;
+    $package =~ s/-/::/g;
+    if ( $RT::CORED_PLUGINS{$package} ) {
+        my ($base_version) = $RT::VERSION =~ /(\d+\.\d+\.\d+)/;
+        die RED, <<"EOT";
+
+**** Error: Your installed version of RT ($RT::VERSION) already
+            contains this extension in core, so you don't need to
+            install it.
+
+            Check https://docs.bestpractical.com/rt/$base_version/RT_Config.html
+            to configure it.
+
+EOT
+    }
+
     # Installation locations
     my %path;
     my $plugin_path;
@@ -223,7 +240,7 @@ sub requires_rt {
     my @sorted = sort RT::Handle::cmp_version $version,$RT::VERSION;
 
     if ($sorted[-1] eq $version) {
-        die <<"EOT";
+        die RED, <<"EOT";
 
 **** Error: This extension requires RT $version. Your installed version
             of RT ($RT::VERSION) is too old.
@@ -249,12 +266,12 @@ sub requires_rt_plugin {
         unshift @INC, $path;
     } else {
         my $name = $self->name;
-        warn <<"EOT";
+        my $msg = <<"EOT";
 
 **** Warning: $name requires that the $plugin plugin be installed and
               enabled; it does not appear to be installed.
-
 EOT
+        warn RED, $msg, RESET, "\n";
     }
     $self->requires(@_);
 }
@@ -264,9 +281,8 @@ sub rt_too_new {
     my $name = $self->name;
     $msg ||= <<EOT;
 
-**** Error: Your installed version of RT (%s) is too new; this extension
-            only works with versions older than %s.
-
+**** Warning: Your installed version of RT (%s) is too new; this extension
+              has not been tested on your version of RT and may not work as expected.
 EOT
     $self->add_metadata("x_rt_too_new", $version) if $self->is_admin;
 
@@ -274,7 +290,7 @@ EOT
     my @sorted = sort RT::Handle::cmp_version $version,$RT::VERSION;
 
     if ($sorted[0] eq $version) {
-        die sprintf($msg,$RT::VERSION,$version);
+        warn RED, sprintf($msg,$RT::VERSION), RESET, "\n";
     }
 }
 
@@ -297,4 +313,4 @@ sub _load_rt_handle {
 
 __END__
 
-#line 468
+#line 484

commit 4646d1a750c1e106ddea3078216e41d0e11c3b48
Author: craig kaiser <craig at bestpractical.com>
Date:   Thu Jan 21 10:57:12 2021 -0500

    Update overlay of NotifySMS::SetRecipients
    
    This change allows for the SetRecipients method to take an arguement of
    'type' which can be 'EmailAddress' ( default ) or 'MobilePhone'. It also
    uses a copy of the RT 5 version of RT::Notify::SetRecipients.

diff --git a/lib/RT/Action/NotifySMS.pm b/lib/RT/Action/NotifySMS.pm
index b210705..6e7aab0 100644
--- a/lib/RT/Action/NotifySMS.pm
+++ b/lib/RT/Action/NotifySMS.pm
@@ -1,22 +1,30 @@
 package RT::Action::NotifySMS;
 
-use base qw(RT::Action);
+use base qw(RT::Action::Notify);
 
 use strict;
 use warnings;
 use LWP::UserAgent;
 
-my @recipients;
-
 sub Prepare {
     my $self = shift;
+    $self->SetRecipients( 'MobilePhone' );
+
+    @{ $self->{'SMS'} } = (
+      @{ $self->{'To'} },
+      @{ $self->{'Cc'} },
+      @{ $self->{'Bcc'} },
+      @{ $self->{'PseudoTo'} }
+    );
 
-    return 0 unless $self->SetRecipients();
-    $self->SUPER::Prepare();
+    return scalar @{ $self->{'SMS'} };
 }
 
+# We overlay the SetRecipients method here in order to get users who may have a
+# Mobile Phone value but no email.
 sub SetRecipients {
     my $self = shift;
+    my $type = shift || 'EmailAddress';
 
     my $ticket = $self->TicketObj;
 
@@ -25,6 +33,7 @@ sub SetRecipients {
 
     my ( @To, @PseudoTo, @Cc, @Bcc );
 
+
     if ( $arg =~ /\bRequestor\b/ ) {
         push @To, $ticket->Requestors->UserMembersObj;
     }
@@ -65,115 +74,130 @@ sub SetRecipients {
                            \b
                            )
                          !x;
-    while ( $arg =~ m/$custom_role_re/g ) {
-        my ( $argument, $role_id, $name, $type ) = ( $1, $2, $3, $4 );
+    while ($arg =~ m/$custom_role_re/g) {
+        my ($argument, $role_id, $name, $type) = ($1, $2, $3, $4);
         my $role;
 
         if ($name) {
-
             # skip anything that is a core Notify argument
-            next
-                if $name eq 'All'
-                || $name eq 'Owner'
-                || $name eq 'Requestor'
-                || $name eq 'AdminCc'
-                || $name eq 'Cc'
-                || $name eq 'OtherRecipients'
-                || $name eq 'AlwaysNotifyActor'
-                || $name eq 'NeverNotifyActor';
+            next if $name eq 'All'
+                 || $name eq 'Owner'
+                 || $name eq 'Requestor'
+                 || $name eq 'AdminCc'
+                 || $name eq 'Cc'
+                 || $name eq 'OtherRecipients'
+                 || $name eq 'AlwaysNotifyActor'
+                 || $name eq 'NeverNotifyActor';
 
             my $roles = RT::CustomRoles->new( $self->CurrentUser );
-            $roles->Limit(
-                FIELD         => 'Name',
-                VALUE         => $name,
-                CASESENSITIVE => 0
-            );
+            $roles->Limit( FIELD => 'Name', VALUE => $name, CASESENSITIVE => 0 );
 
             # custom roles are named uniquely, but just in case there are
             # multiple matches, bail out as we don't know which one to use
             $role = $roles->First;
-            if ($role) {
+            if ( $role ) {
                 $role = undef if $roles->Next;
             }
-        } else {
+        }
+        else {
             $role = RT::CustomRole->new( $self->CurrentUser );
-            $role->Load($role_id);
+            $role->Load( $role_id );
         }
 
-        unless ( $role && $role->id ) {
-            $RT::Logger->debug(
-                "Unable to load custom role from scrip action argument '$argument'"
-            );
+        unless ($role && $role->id) {
+            $RT::Logger->debug("Unable to load custom role from scrip action argument '$argument'");
             next;
         }
 
         my @role_members = (
-            $ticket->RoleGroup( $role->GroupType )->UserMembersObj,
-            $ticket->QueueObj->RoleGroup( $role->GroupType )
-                ->UserMembersObj,
+            $ticket->RoleGroup($role->GroupType)->UserMembersObj,
+            $ticket->QueueObj->RoleGroup($role->GroupType)->UserMembersObj,
         );
-        push @To, @role_members;
+
+        if (!$type || $type eq 'Cc') {
+            push @Cc, @role_members;
+        }
+        elsif ($type eq 'Bcc') {
+            push @Bcc, @role_members;
+        }
+        elsif ($type eq 'To') {
+            push @To, @role_members;
+        }
     }
 
     if ( $arg =~ /\bCc\b/ ) {
-        push( @To, $ticket->Cc->UserMembersObj );
-        push( @To, $ticket->QueueObj->Cc->UserMembersObj );
+
+        #If we have a To, make the Ccs, Ccs, otherwise, promote them to To
+        if (@To) {
+            push ( @Cc, $ticket->Cc->UserMembersObj );
+            push ( @Cc, $ticket->QueueObj->Cc->UserMembersObj  );
+        }
+        else {
+            push ( @Cc, $ticket->Cc->UserMembersObj  );
+            push ( @To, $ticket->QueueObj->Cc->UserMembersObj  );
+        }
     }
+
     if (   $arg =~ /\bOwner\b/
         && $ticket->OwnerObj->id != RT->Nobody->id
-        && not $ticket->OwnerObj->Disabled )
-    {
-        my $role_group = $self->TicketObj->RoleGroup('Owner');
-        push( @To, $role_group->UserMembersObj );
+        && not $ticket->OwnerObj->Disabled
+    ) {
+        # If we're not sending to Ccs or requestors,
+        # then the Owner can be the To.
+        if (@To) {
+            push ( @Bcc, $ticket->OwnerObj );
+        }
+        else {
+            push ( @To, $ticket->OwnerObj );
+        }
+
     }
 
     if ( $arg =~ /\bAdminCc\b/ ) {
-        push( @To, $ticket->AdminCc->UserMembersObj );
-        push( @To, $ticket->QueueObj->AdminCc->UserMembersObj );
+        push ( @Bcc, $ticket->AdminCc->UserMembersObj  );
+        push ( @Bcc, $ticket->QueueObj->AdminCc->UserMembersObj  );
     }
 
     if ( RT->Config->Get('UseFriendlyToLine') ) {
         unless (@To) {
             push @PseudoTo,
-                sprintf RT->Config->Get('FriendlyToLineFormat'), $arg,
-                $ticket->id;
+                sprintf RT->Config->Get('FriendlyToLineFormat'), $arg, $ticket->id;
         }
     }
 
-    my @NoSquelch;
+    my $getUsersAttr = sub {
+      my $collection = shift;
+
+      my @temp = ();
+      foreach my $users ( @{$collection} ) {
+          if ( ref $users eq 'RT::User' ) {
+              next unless $users->$type;
+              push @temp, $users->$type;
+          }
+          else {
+              while ( my $user = $users->Next ) {
+                  next unless $user->$type;
+                  push @temp, $user->$type;
+              }
+          }
+      };
+
+      return @temp;
+    };
+
+    @{ $self->{'To'} }       = &$getUsersAttr ( \@To );
+    @{ $self->{'Cc'} }       = &$getUsersAttr ( \@Cc );
+    @{ $self->{'Bcc'} }      = &$getUsersAttr ( \@Bcc );
+    @{ $self->{'PseudoTo'} } = &$getUsersAttr ( \@PseudoTo );
+
     if ( $arg =~ /\bOtherRecipients\b/ ) {
         if ( my $attachment = $self->TransactionObj->Attachments->First ) {
-            push @NoSquelch, map $_->address,
+            push @{ $self->{'NoSquelch'}{'Cc'} ||= [] }, map $_->address,
                 Email::Address->parse( $attachment->GetHeader('RT-Send-Cc') );
-            push @NoSquelch, map $_->address,
-                Email::Address->parse(
-                $attachment->GetHeader('RT-Send-Bcc') );
-        }
-    }
-
-    # See if we can get some phone numbers from our NoSquelched emails
-    if ( @NoSquelch ) {
-        my $user = RT::User->new(RT->SystemUser);
-        foreach my $email (@NoSquelch) {
-            my ($ret, $msg) = $user->Load($email);
-            RT::Logger->info($msg) unless $ret;
-
-            push @To, $user->MobilePhone unless ! $user->MobilePhone;
+            push @{ $self->{'NoSquelch'}{'Bcc'} ||= [] }, map $_->address,
+                Email::Address->parse( $attachment->GetHeader('RT-Send-Bcc') );
         }
     }
-
-    my $user = RT::User->new( RT->SystemUser );
-    my @recipients;
-
-    foreach my $role (@To) {
-        while (my $user = $role->Next) {
-            push @recipients, $user->MobilePhone
-                unless !$user->MobilePhone;
-        }
-    }
-    return 0 unless scalar @recipients;
-
-    @{ $self->{'Recipients'} } = @recipients;
 }
 
 sub Commit {
@@ -188,9 +212,13 @@ sub Commit {
     }
 
     my $content = $self->TemplateObj->MIMEObj->as_string;
+    unless ( $content ) {
+        RT::Logger->debug( 'No message found, not sending SMS' );
+        return 1;
+    }
 
     my ( $ret, $msg ) = $self->ScripActionObj->Action->SendMessage(
-        Recipients => $self->{Recipients},
+        Recipients => $self->{'SMS'},
         Msg        => $content,
     );
 
diff --git a/lib/RT/Action/NotifyTwilio.pm b/lib/RT/Action/NotifyTwilio.pm
index 483dcfe..8a8bb36 100644
--- a/lib/RT/Action/NotifyTwilio.pm
+++ b/lib/RT/Action/NotifyTwilio.pm
@@ -39,10 +39,6 @@ sub SendMessage {
             unless RT::Config->Get($config);
     }
 
-    return ( 0, 'Please provide a message to send' ) unless $args{Msg};
-    return ( 0, 'Please provide a recipient' )
-        unless scalar $args{Recipients};
-
     my %Credentials = (
         account_id => RT::Config->Get('TwilioAccounId'),
         auth_token => RT::Config->Get('TwilioAuthToken'),

commit 24518b8fbb1ba421de5ba20e97d8f92e3a2094a0
Author: craig kaiser <craig at bestpractical.com>
Date:   Mon Jan 25 12:09:34 2021 -0500

    Parse template object in Prepare method if no MIMEObj exist
    
    A MIMEObj needs to exist in order for preview scrips code to run without
    error.

diff --git a/lib/RT/Action/NotifySMS.pm b/lib/RT/Action/NotifySMS.pm
index 6e7aab0..61a62eb 100644
--- a/lib/RT/Action/NotifySMS.pm
+++ b/lib/RT/Action/NotifySMS.pm
@@ -17,6 +17,15 @@ sub Prepare {
       @{ $self->{'PseudoTo'} }
     );
 
+     unless ( $self->TemplateObj->MIMEObj ) {
+        my ( $ret, $msg ) = $self->TemplateObj->Parse(
+            Argument       => $self->Argument,
+            TicketObj      => $self->TicketObj,
+            TransactionObj => $self->TransactionObj
+        );
+        RT::Logger->error( "Could not parse SMS template: $msg" ) unless $ret;
+    }
+
     return scalar @{ $self->{'SMS'} };
 }
 
@@ -203,14 +212,6 @@ sub SetRecipients {
 sub Commit {
     my $self = shift;
 
-    unless ( $self->TemplateObj->MIMEObj ) {
-        my ( $result, $message ) = $self->TemplateObj->Parse(
-            Argument       => $self->Argument,
-            TicketObj      => $self->TicketObj,
-            TransactionObj => $self->TransactionObj
-        );
-    }
-
     my $content = $self->TemplateObj->MIMEObj->as_string;
     unless ( $content ) {
         RT::Logger->debug( 'No message found, not sending SMS' );

commit ae7cb3d28b3bd93492cb2550400ebf5016d3c721
Author: craig kaiser <craig at bestpractical.com>
Date:   Mon Jan 25 15:23:04 2021 -0500

    Make documentation clearer

diff --git a/README b/README
index d63b383..9f66115 100644
--- a/README
+++ b/README
@@ -3,22 +3,11 @@ NAME
     messages.
 
 DESCRIPTION
-    Provide additional actions for Scrips, that allow for the sending of
-    messages inplace of email. The new action can be loaded in the web UI
-    from:
-
-        Global -> Actions -> Create
-
-    where the action module is one of the notify option from this extension:
-
-        "NotifyTwilio"
-
-    For the action you can choose to pass the following parameters:
-
-        All, Owner, Requestor, AdminCc, Cc
+    Provide additional actions for Scrips, that allow for the sending of SMS
+    messages alongside of email.
 
 RT VERSION
-    Works with RT 4.4.0
+    Works with RT 5.
 
 INSTALLATION
     perl Makefile.PL
@@ -32,7 +21,7 @@ INSTALLATION
         If you run this twice, you may end up with duplicate data in your
         database.
 
-    Edit your /opt/rt4/etc/RT_SiteConfig.pm
+    Edit your /opt/rt5/etc/RT_SiteConfig.pm
         If you are using RT 4.4 or greater, add this line:
 
             Plugin('RT::Extension::NotifySMS');
@@ -41,10 +30,50 @@ INSTALLATION
         action is being used, see the module for specifications.
 
     Clear your mason cache
-            rm -rf /opt/rt4/var/mason_data/obj
+            rm -rf /opt/rt5/var/mason_data/obj
 
     Restart your webserver
 
+CONFIGURATION
+  Twilio
+    The `make initdb` command creates a new RT::Action called Notify Twilio.
+
+    You can now use this action in your RT::Scrips, just like existing
+    notification scrips use email notification actions.
+
+    By default the Notify Twilio action provides alerts to all of the
+    following roles:
+
+        Owner, Requestor, AdminCc, Cc
+
+    If you'd like a more specific role on a ticket notified, then you can
+    create a new action in the RT web UI:
+
+        Admin->Global->Actions
+
+    Where the "Action Module" is "NotifyTwilio". Then in the "Parameters to
+    Pass" section you can provide one or more of the following options:
+
+        All, Owner, Requestor, AdminCc, Cc
+
+    It is important to remember that only user records that have a value for
+    the "Mobile Phone" attribute will be able to receive SMS alerts.
+
+   NotifyTwilio
+    Send a message using the Twilio web api, requires the follow config
+    values from RT_SiteConfig.pm:
+
+            Set($TwilioAccounId, 'Secret');
+            Set($TwilioAuthToken, 'Secret');
+            Set($APIURL, 'https://api.twilio.com/2010-04-01/Accounts/');
+            Set($APIDomain, 'api.twilio.com:443');
+            Set($APIRealm, 'Twilio API');
+            Set($MessageSender, '0123456789');
+
+    To obtain the Twilio AuthToken and AccountId create a new project of
+    type programmable sms. Once done setting up the project you will have
+    access to the projects AccountId and AuthToken.
+
 AUTHOR
     Best Practical Solutions, LLC <modules at bestpractical.com>
 
diff --git a/etc/initialdata b/etc/initialdata
index b258949..44fd355 100644
--- a/etc/initialdata
+++ b/etc/initialdata
@@ -1,7 +1,7 @@
 push @ScripActions, (
     {
         Name        => 'Notify Twilio',
-        Description => 'Send SMS messages using Twilio API',
+        Description => 'Send SMS Messages Using Twilio API To All Roles',
         ExecModule  => 'NotifyTwilio',
         Argument    => 'All',
     },
diff --git a/lib/RT/Action/NotifyTwilio.pm b/lib/RT/Action/NotifyTwilio.pm
index 8a8bb36..db82c1e 100644
--- a/lib/RT/Action/NotifyTwilio.pm
+++ b/lib/RT/Action/NotifyTwilio.pm
@@ -7,23 +7,6 @@ use warnings;
 use LWP::UserAgent;
 use JSON qw(decode_json);
 
-=head2 NotifyTwilio
-
-Send a message using the Twilio web api, requires the follow
-config values from RT_SiteConfig.pm:
-
-        Set($TwilioAccounId, 'Secret');
-        Set($TwilioAuthToken, 'Secret');
-        Set($APIURL, 'https://api.twilio.com/2010-04-01/Accounts/');
-        Set($APIDomain, 'api.twilio.com:443');
-        Set($APIRealm, 'Twilio API');
-        Set($MessageSender, '0123456789');
-
-To obtain the Twilio AuthToken and AccountId create a new project of type
-programmable sms. Once done setting up the project you will have access to
-the projects AccountId and AuthToken.
-=cut
-
 sub SendMessage {
     my $self = shift;
     my %args = (
diff --git a/lib/RT/Extension/NotifySMS.pm b/lib/RT/Extension/NotifySMS.pm
index 7ae2953..3195e49 100644
--- a/lib/RT/Extension/NotifySMS.pm
+++ b/lib/RT/Extension/NotifySMS.pm
@@ -11,22 +11,12 @@ RT-Extension-NotifySMS - Provide additional actions to send text messages.
 
 =head1 DESCRIPTION
 
-Provide additional actions for Scrips, that allow for the sending of messages
-inplace of email. The new action can be loaded in the web UI from:
-
-    Global -> Actions -> Create
-
-where the action module is one of the notify option from this extension:
-
-    "NotifyTwilio"
-
-For the action you can choose to pass the following parameters:
-
-    All, Owner, Requestor, AdminCc, Cc
+Provide additional actions for Scrips, that allow for the sending of SMS
+messages alongside of email.
 
 =head1 RT VERSION
 
-Works with RT 4.4.0
+Works with RT 5.
 
 =head1 INSTALLATION
 
@@ -47,7 +37,7 @@ Only run this the first time you install this module.
 If you run this twice, you may end up with duplicate data
 in your database.
 
-=item Edit your F</opt/rt4/etc/RT_SiteConfig.pm>
+=item Edit your F</opt/rt5/etc/RT_SiteConfig.pm>
 
 If you are using RT 4.4 or greater, add this line:
 
@@ -58,12 +48,56 @@ sms action is being used, see the module for specifications.
 
 =item Clear your mason cache
 
-    rm -rf /opt/rt4/var/mason_data/obj
+    rm -rf /opt/rt5/var/mason_data/obj
 
 =item Restart your webserver
 
 =back
 
+=head1 CONFIGURATION
+
+=head2 Twilio
+
+The `make initdb` command creates a new RT::Action called Notify Twilio.
+
+You can now use this action in your RT::Scrips, just like existing notification
+scrips use email notification actions.
+
+By default the Notify Twilio action provides alerts to all of the following roles:
+
+    Owner, Requestor, AdminCc, Cc
+
+If you'd like a more specific role on a ticket notified, then you can create a new
+action in the RT web UI:
+
+    Admin->Global->Actions
+
+Where the "Action Module" is "NotifyTwilio". Then in the "Parameters to Pass" section
+you can provide one or more of the following options:
+
+    All, Owner, Requestor, AdminCc, Cc
+
+It is important to remember that only user records that have a value
+for the "Mobile Phone" attribute will be able to receive SMS alerts.
+
+=head3 NotifyTwilio
+
+Send a message using the Twilio web api, requires the follow
+config values from RT_SiteConfig.pm:
+
+        Set($TwilioAccounId, 'Secret');
+        Set($TwilioAuthToken, 'Secret');
+        Set($APIURL, 'https://api.twilio.com/2010-04-01/Accounts/');
+        Set($APIDomain, 'api.twilio.com:443');
+        Set($APIRealm, 'Twilio API');
+        Set($MessageSender, '0123456789');
+
+To obtain the Twilio AuthToken and AccountId create a new project of type
+programmable sms. Once done setting up the project you will have access to
+the projects AccountId and AuthToken.
+
+=cut
+
 =head1 AUTHOR
 
 Best Practical Solutions, LLC E<lt>modules at bestpractical.comE<gt>

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


More information about the Bps-public-commit mailing list