[Rt-commit] rt branch, 4.4/add-role-by-username, created. rt-4.4.2-226-g222c890d1

? sunnavy sunnavy at bestpractical.com
Tue Apr 24 13:13:06 EDT 2018


The branch, 4.4/add-role-by-username has been created
        at  222c890d1468223da70ed95e2dccf495e1b62ce4 (commit)

- Log -----------------------------------------------------------------
commit 19840dbc0d060188ffbbe8cd43f1f39d8bb9d354
Author: Jim Brandt <jbrandt at bestpractical.com>
Date:   Wed Jan 10 16:40:40 2018 -0500

    Accept usernames for roles on ticket create
    
    In addition to being able to add an RT user to a role
    with an email address, also accept a valid RT username via the
    web UI on create.

diff --git a/lib/RT/Record/Role/Roles.pm b/lib/RT/Record/Role/Roles.pm
index 1a88793ae..ef990ef61 100644
--- a/lib/RT/Record/Role/Roles.pm
+++ b/lib/RT/Record/Role/Roles.pm
@@ -621,21 +621,10 @@ sub _ResolveRoles {
                             $self->loc("Couldn't load principal: [_1]", $msg);
                     }
                 } else {
-                    my @addresses = RT::EmailParser->ParseEmailAddress( $value );
-                    for my $address ( @addresses ) {
-                        my $user = RT::User->new( RT->SystemUser );
-                        my ($id, $msg) = $user->LoadOrCreateByEmail( $address );
-                        if ( $id ) {
-                            # Load it back as us, not as the system
-                            # user, to be completely safe.
-                            $user = RT::User->new( $self->CurrentUser );
-                            $user->Load( $id );
-                            push @{ $roles->{$role} }, $user->PrincipalObj;
-                        } else {
-                            push @errors,
-                                $self->loc("Couldn't load or create user: [_1]", $msg);
-                        }
-                    }
+                    my ($users, $errors) = $self->ParseInputPrincipals( $value );
+
+                    push @{ $roles->{$role} }, map { $_->PrincipalObj } @{$users};
+                    push @errors, @$errors if @$errors;
                 }
             }
         }
@@ -643,6 +632,79 @@ sub _ResolveRoles {
     return (@errors);
 }
 
+=head2 ParseInputPrincipals
+
+In the RT web UI, some watcher input fields can accept RT users
+identified by email address or RT username. On the ticket Create
+and Update pages, these fields can have multiple values submitted
+as a comma-separated list. This method parses such lists and returns
+an array of user objects found or created for each parsed value.
+
+C<ParseEmailAddress> in L<RT::EmailParser> provides a similar
+function, but only handles email addresses, filtering out
+usernames. It also returns a list of L<Email::Address> objects
+rather than RT objects.
+
+Accepts: a string with usernames and email addresses
+
+Returns: arrayref of RT::User objects, arrayref of any error strings
+
+=cut
+
+sub ParseInputPrincipals {
+    my $self = shift;
+    my $input_string = shift;
+
+    # Some broken mailers send:  ""Vincent, Jesse"" <jesse at fsck.com>
+    $input_string =~ s/\"\"(.*?)\"\"/\"$1\"/g;
+
+    my @list = Email::Address::List->parse(
+        $input_string,
+        skip_comments => 1,
+        skip_groups => 1,
+    );
+
+    my @principals; # Collect user or group objects
+    my @errors;
+
+    foreach my $e ( @list ) {
+        my $user = RT::User->new( RT->SystemUser );
+
+        if ($e->{'type'} eq 'mailbox') {
+            if ($e->{'not_ascii'}) {
+                RT::Logger->error($e->{'value'} ." contains non-ASCII values");
+                next;
+            }
+
+            my ($id, $msg) = $user->LoadOrCreateByEmail( $e->{'value'} );
+            if ( $id ) {
+                push @principals, $user;
+            }
+            else {
+                push @errors, $self->loc("Couldn't load or create user: [_1]", $msg);
+                RT::Logger->error("Couldn't load or create user from email address " . $e->{'value'} . ", " . $msg);
+            }
+        }
+        elsif ( $e->{'value'} =~ /^\s*(\w+)\s*$/ ) {
+            # Email::Address::List found a value that doesn't look like an email
+            my ($id, $msg) = $user->Load( $1 );
+            if ($id) {
+                push @principals, $user;
+            }
+            else {
+                push @errors, $self->loc("Couldn't load or create user: [_1]", $msg);
+                RT::Logger->error("Couldn't load or create user from username " . $e->{'value'} . ", " . $msg);
+            }
+        }
+        else {
+            push @errors, $self->loc("Couldn't load or create user: [_1]", $e->{'value'});
+            RT::Logger->warn($e->{'value'} . " is not a valid email address or username");
+        }
+    }
+
+    return (\@principals, \@errors);
+}
+
 sub _CreateRoleGroup {
     my $self = shift;
     my $name = shift;
diff --git a/share/html/Ticket/Create.html b/share/html/Ticket/Create.html
index c8b73f4e1..81caf366b 100644
--- a/share/html/Ticket/Create.html
+++ b/share/html/Ticket/Create.html
@@ -488,6 +488,9 @@ if ( !exists $ARGS{'AddMoreAttach'} && ($ARGS{'id'}||'') eq 'new' ) {
         my $value = $ARGS{ $field };
         next unless defined $value && length $value;
 
+        # Preserve non-email username inputs
+        my @usernames = grep {!/\@/} split /,/, $value;
+
         my @emails = Email::Address->parse( $value );
         foreach my $email ( grep RT::EmailParser->IsRTAddress($_->address), @emails ) {
             push @results, loc("[_1] is an address RT receives mail at. Adding it as a '[_2]' would create a mail loop", $email->format, loc($field =~ /^(.*?)s?$/) );
@@ -495,6 +498,11 @@ if ( !exists $ARGS{'AddMoreAttach'} && ($ARGS{'id'}||'') eq 'new' ) {
             $email = undef;
         }
         $ARGS{ $field } = join ', ', map $_->format, grep defined, @emails;
+
+        if ( @usernames ){
+            # Restore usernames, if any
+            $ARGS{ $field } .= ', ' . join ', ', grep defined, @usernames;
+        }
     }
 }
 

commit 222c890d1468223da70ed95e2dccf495e1b62ce4
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Thu Apr 12 03:48:53 2018 +0800

    Accept usernames for one time Cc/Bcc on ticket update

diff --git a/lib/RT/Ticket.pm b/lib/RT/Ticket.pm
index e8046c446..09832ade8 100644
--- a/lib/RT/Ticket.pm
+++ b/lib/RT/Ticket.pm
@@ -1685,10 +1685,12 @@ sub _RecordNote {
 
     foreach my $type (qw/Cc Bcc/) {
         if ( defined $args{ $type . 'MessageTo' } ) {
-
-            my $addresses = join ', ', (
-                map { RT::User->CanonicalizeEmailAddress( $_->address ) }
-                    Email::Address->parse( $args{ $type . 'MessageTo' } ) );
+            my ( $users, $errors ) = $self->ParseInputPrincipals( $args{ $type . 'MessageTo' } );
+            my $addresses = join ', ',
+              (
+                map { RT::User->CanonicalizeEmailAddress( $_ ) }
+                map { $_->EmailAddress || () } @$users
+              );
             $args{'MIMEObj'}->head->replace( 'RT-Send-' . $type, Encode::encode( "UTF-8", $addresses ) );
         }
     }
diff --git a/share/html/Ticket/Update.html b/share/html/Ticket/Update.html
index 6e73b50a8..dcd21f323 100644
--- a/share/html/Ticket/Update.html
+++ b/share/html/Ticket/Update.html
@@ -339,6 +339,9 @@ if ( $ARGS{'SubmitTicket'} ) {
         my $value = $ARGS{ $field };
         next unless defined $value && length $value;
 
+        # Preserve non-email username inputs
+        my @usernames = grep {!/\@/} split /,/, $value;
+
         my @emails = Email::Address->parse( $value );
         foreach my $email ( grep RT::EmailParser->IsRTAddress($_->address), @emails ) {
             push @results, loc("[_1] is an address RT receives mail at. Adding it as a '[_2]' would create a mail loop", $email->format, loc(substr($field, 6)) );
@@ -346,6 +349,11 @@ if ( $ARGS{'SubmitTicket'} ) {
             $email = undef;
         }
         $ARGS{ $field } = join ', ', map $_->format, grep defined, @emails;
+
+        if ( @usernames ){
+            # Restore usernames, if any
+            $ARGS{ $field } .= ', ' . join ', ', grep defined, @usernames;
+        }
     }
 }
 

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


More information about the rt-commit mailing list