[Rt-commit] rt branch, 5.0-trunk, updated. rt-5.0.0-212-g2bbdbb13d7
Jim Brandt
jbrandt at bestpractical.com
Fri Jan 8 12:03:54 EST 2021
The branch, 5.0-trunk has been updated
via 2bbdbb13d79b13229adcd093d1bb66bbb24e0d74 (commit)
via 31b619d5aad002e97a2883bf1fa6fc5fc89a2c76 (commit)
via 30abd52e8eff70f3c61a46b3c4bae13ab6e0fb8c (commit)
via 8b89dd23c66551561549e775f2e3248ac820749d (commit)
via 7b375e0b77f40609c0c33eb7323068e0b978d5b2 (commit)
from 5af84f496f3a8a0dfd08950f1a413866fa88af69 (commit)
Summary of changes:
lib/RT/REST2.pm | 8 +-
lib/RT/REST2/Resource/Message.pm | 21 +---
lib/RT/REST2/Resource/Record/Writable.pm | 42 ++------
lib/RT/REST2/Resource/Ticket.pm | 16 ++-
lib/RT/REST2/Util.pm | 25 ++++-
t/rest2/data/html.htm | 1 +
t/rest2/data/plain.txt | 1 +
t/rest2/tickets.t | 170 +++++++++++++++++++++++++++++++
8 files changed, 227 insertions(+), 57 deletions(-)
create mode 100644 t/rest2/data/html.htm
create mode 100644 t/rest2/data/plain.txt
- Log -----------------------------------------------------------------
commit 8b89dd23c66551561549e775f2e3248ac820749d
Author: sunnavy <sunnavy at bestpractical.com>
Date: Wed Oct 28 04:40:32 2020 +0800
Fix typo in documentation
diff --git a/lib/RT/REST2.pm b/lib/RT/REST2.pm
index e7a4f6d27e..fade9fa963 100644
--- a/lib/RT/REST2.pm
+++ b/lib/RT/REST2.pm
@@ -295,7 +295,7 @@ The time, in minutes, you've taken to work on your response/comment, optional.
=head3 Add Attachments
You can attach any binary or text file to your response or comment by
-specifying C<Attachements> property in the JSON object, which should be a
+specifying C<Attachments> property in the JSON object, which should be a
JSON array where each item represents a file you want to attach. Each item
is a JSON object with the following properties:
commit 30abd52e8eff70f3c61a46b3c4bae13ab6e0fb8c
Author: Dianne Skoll <dianne at bestpractical.com>
Date: Wed Oct 28 04:46:34 2020 +0800
Allow attachments to be added when a ticket is created
Thanks to gibus and puck contributing updates via the
rt-extension-rest2 extension on github.
diff --git a/lib/RT/REST2.pm b/lib/RT/REST2.pm
index fade9fa963..3ffc94ca96 100644
--- a/lib/RT/REST2.pm
+++ b/lib/RT/REST2.pm
@@ -294,10 +294,10 @@ The time, in minutes, you've taken to work on your response/comment, optional.
=head3 Add Attachments
-You can attach any binary or text file to your response or comment by
-specifying C<Attachments> property in the JSON object, which should be a
-JSON array where each item represents a file you want to attach. Each item
-is a JSON object with the following properties:
+You can attach any binary or text file to a ticket via create, correspond, or
+comment by adding an C<Attachments> property in the JSON object. The value
+should be a JSON array where each item represents a file you want to attach.
+Each item is a JSON object with the following properties:
=over 4
diff --git a/lib/RT/REST2/Resource/Record/Writable.pm b/lib/RT/REST2/Resource/Record/Writable.pm
index d603bd090b..bff09cf3ce 100644
--- a/lib/RT/REST2/Resource/Record/Writable.pm
+++ b/lib/RT/REST2/Resource/Record/Writable.pm
@@ -112,6 +112,10 @@ sub from_multipart {
$json->{CustomFields} = $cfs;
}
+ if ( my @attachments = $self->request->upload('Attachments') ) {
+ $json->{Attachments} = [ process_uploads(@attachments) ];
+ }
+
return $self->from_json($json);
}
diff --git a/lib/RT/REST2/Resource/Ticket.pm b/lib/RT/REST2/Resource/Ticket.pm
index 02a020d02c..5054dc2321 100644
--- a/lib/RT/REST2/Resource/Ticket.pm
+++ b/lib/RT/REST2/Resource/Ticket.pm
@@ -91,13 +91,27 @@ sub create_record {
Object => $queue,
) and $queue->Disabled != 1;
- if ( defined $data->{Content} ) {
+ if ( defined $data->{Content} || defined $data->{Attachments} ) {
$data->{MIMEObj} = HTML::Mason::Commands::MakeMIMEEntity(
Interface => 'REST',
Subject => $data->{Subject},
Body => delete $data->{Content},
Type => delete $data->{ContentType} || 'text/plain',
);
+ if ( defined $data->{Attachments} ) {
+ return (\400, "Attachments must be an array") unless ref($data->{Attachments}) eq 'ARRAY';
+ foreach my $attachment (@{$data->{Attachments}}) {
+ return (\400, "Each element of Attachments must be a hash") unless ref($attachment) eq 'HASH';
+ foreach my $field (qw(FileName FileType FileContent)) {
+ return (\400, "Field $field is required for each attachment in Attachments") unless $attachment->{$field};
+ }
+ $data->{MIMEObj}->attach(
+ Type => $attachment->{FileType},
+ Filename => $attachment->{FileName},
+ Data => MIME::Base64::decode_base64($attachment->{FileContent}));
+ }
+ delete $data->{Attachments};
+ }
}
my ($ok, $txn, $msg) = $self->_create_record($data);
diff --git a/lib/RT/REST2/Util.pm b/lib/RT/REST2/Util.pm
index f0884123cb..dc2bf92b81 100644
--- a/lib/RT/REST2/Util.pm
+++ b/lib/RT/REST2/Util.pm
@@ -218,6 +218,7 @@ sub deserialize_record {
# Sanitize input for the Perl API
for my $field (sort keys %$data) {
next if $field eq 'CustomFields';
+ next if $field eq 'Attachments';
my $value = $data->{$field};
next unless ref $value;
diff --git a/t/rest2/data/html.htm b/t/rest2/data/html.htm
new file mode 100644
index 0000000000..abce6679d6
--- /dev/null
+++ b/t/rest2/data/html.htm
@@ -0,0 +1 @@
+<p><i>Easy</i> as π</p>
diff --git a/t/rest2/data/plain.txt b/t/rest2/data/plain.txt
new file mode 100644
index 0000000000..8ab686eafe
--- /dev/null
+++ b/t/rest2/data/plain.txt
@@ -0,0 +1 @@
+Hello, World!
diff --git a/t/rest2/tickets.t b/t/rest2/tickets.t
index 1642e80f3f..9b9b0fdb43 100644
--- a/t/rest2/tickets.t
+++ b/t/rest2/tickets.t
@@ -4,6 +4,8 @@ use RT::Test::REST2 tests => undef;
use Test::Deep;
use MIME::Base64;
+use Encode qw(decode encode);
+
# Test using integer priorities
RT->Config->Set(EnablePriorityAsString => 0);
my $mech = RT::Test::REST2->mech;
@@ -508,4 +510,131 @@ my ($ticket_url, $ticket_id);
like($third_ticket->{_url}, qr{$rest_base_path/ticket/$ticket3_id$});
}
+# Ticket Creation - with attachments
+{
+ my $payload = {
+ Subject => 'Ticket creation using REST, with attachments.',
+ Queue => 'General',
+ Content => 'Testing ticket creation with attachments using REST API.',
+ Attachments => [
+ { FileName => 'plain.txt',
+ FileType => 'text/plain',
+ FileContent => MIME::Base64::encode_base64('Hello, World!')
+ },
+ { FileName => 'html.htm',
+ FileType => 'text/html',
+ FileContent => MIME::Base64::encode_base64(
+ encode( 'UTF-8', "<p><i>Easy</i> as \x{03c0}</p>" )
+ ),
+ },
+ { FileName => 'moon.png',
+ FileType => 'image/png',
+ FileContent =>
+ 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAADfSURBVDiNndM9TsNAFATgzy5yjZSAE85JBygETgENUPF3iBCitHAFQkcIhZ/Ryn9gRlrZmp2Z3ef3TBOHOMULPrDBMrhpi/4HI5xjix2+4nmJRbx/Yh7ahvkpRPVV4QDXwT3UQy46zGkAZDgK/iytefvHgCrkJsqZUH6cLnNbABSxd5Jhhf1IbkMXv8Qux7hH1Ic1xvk/jBWy6gavumvtwx7ectwZXkKh7MA95XgObeOtpI2U4zl0kGbpxgiPvwQUcXLrKFchc82f6Ur0PK49azOnmOI4TBu84zm4SV38DeIVYkrYJyNbAAAAAElFTkSuQmCC'
+ },
+ ]
+ };
+
+ my $res = $mech->post_json( "$rest_base_path/ticket", $payload,
+ 'Authorization' => $auth, );
+ is( $res->code, 201 );
+ ok( $ticket_url = $res->header('location') );
+ ok( ($ticket_id) = $ticket_url =~ qr[/ticket/(\d+)] );
+}
+
+# We have the attachments added above
+{
+ my $ticket = RT::Ticket->new($user);
+ $ticket->Load($ticket_id);
+ my $transaction_id = $ticket->Transactions->Last->id;
+ my $attachments = $ticket->Attachments->ItemsArrayRef;
+
+ # The 5 attachments are:
+ # 1) Top-level multipart
+ # 2) Top-level ticket content
+ # 3-5) The three attachments added in the Attachments array
+ is( scalar(@$attachments), 5 );
+
+ is( $attachments->[0]->ContentType, 'multipart/mixed' );
+
+ is( $attachments->[1]->ContentType, 'text/plain' );
+ is( $attachments->[1]->Content,
+ 'Testing ticket creation with attachments using REST API.' );
+
+ is( $attachments->[2]->ContentType, 'text/plain' );
+ is( $attachments->[2]->Filename, 'plain.txt' );
+ is( $attachments->[2]->Content, 'Hello, World!' );
+
+ is( $attachments->[3]->ContentType, 'text/html' );
+ is( $attachments->[3]->Filename, 'html.htm' );
+ is( $attachments->[3]->Content, "<p><i>Easy</i> as \x{03c0}</p>" );
+
+ is( $attachments->[4]->ContentType, 'image/png' );
+ is( $attachments->[4]->Filename, 'moon.png' );
+ like( $attachments->[4]->Content, qr/IHDR/, "Looks like a PNG image" );
+}
+
+# Ticket Creation - with attachments, using multipart/form-data
+my $json = JSON->new->utf8;
+{
+ my $plain_name = 'plain.txt';
+ my $plain_path = RT::Test::get_relocatable_file($plain_name, 'data');
+ my $html_name = 'html.htm';
+ my $html_path = RT::Test::get_relocatable_file($html_name, 'data');
+ my $img_name = 'image.png';
+ my $img_path = RT::Test::get_relocatable_file($img_name, 'data');
+
+ my $payload = {
+ Subject => 'Ticket creation using REST, multipart/form-data, with attachments.',
+ Queue => 'General',
+ Content => 'Testing ticket creation, multipart/form-data, with attachments using REST API.',
+ };
+
+ my $res = $mech->post( "$rest_base_path/ticket", $payload,
+ 'Authorization' => $auth,
+ 'Content_Type' => 'form-data',
+ 'Content' => [
+ 'JSON' => $json->encode($payload),
+ 'Attachments' => [$plain_path, $plain_name, 'text/plain'],
+ 'Attachments' => [$html_path, $html_name, 'text/html' ],
+ 'Attachments' => [$img_path, $img_name, 'image/png' ]
+ ]);
+ is( $res->code, 201 );
+ ok( $ticket_url = $res->header('location') );
+ ok( ($ticket_id) = $ticket_url =~ qr[/ticket/(\d+)] );
+}
+
+# Validate that the ticket was created correctly
+
+{
+ my $ticket = RT::Ticket->new($user);
+ $ticket->Load($ticket_id);
+ my $transaction_id = $ticket->Transactions->Last->id;
+ my $attachments = $ticket->Attachments->ItemsArrayRef;
+
+ # The 5 attachments are:
+ # 1) Top-level multipart
+ # 2) Top-level ticket content
+ # 3-5) The three attachments added in the Attachments array
+ is( scalar(@$attachments), 5 );
+
+ is( $attachments->[0]->ContentType, 'multipart/mixed' );
+
+ is( $attachments->[1]->ContentType, 'text/plain' );
+ is( $attachments->[1]->Content,
+ 'Testing ticket creation, multipart/form-data, with attachments using REST API.' );
+
+ is( $attachments->[2]->ContentType, 'text/plain' );
+ is( $attachments->[2]->Filename, 'plain.txt' );
+ is( $attachments->[2]->Content, "Hello, World!\n" );
+
+ is( $attachments->[3]->ContentType, 'text/html' );
+ is( $attachments->[3]->Filename, 'html.htm' );
+ is( $attachments->[3]->Content, "<p><i>Easy</i> as \x{03c0}</p>\n" );
+
+ is( $attachments->[4]->ContentType, 'image/png' );
+ is( $attachments->[4]->Filename, 'image.png' );
+ like( $attachments->[4]->Content, qr/IHDR/, "Looks like a PNG image" );
+}
+
done_testing;
commit 31b619d5aad002e97a2883bf1fa6fc5fc89a2c76
Author: sunnavy <sunnavy at bestpractical.com>
Date: Thu Oct 29 05:55:19 2020 +0800
Test custom field uploads on ticket create for REST2
diff --git a/t/rest2/tickets.t b/t/rest2/tickets.t
index 9b9b0fdb43..72e1f6a011 100644
--- a/t/rest2/tickets.t
+++ b/t/rest2/tickets.t
@@ -637,4 +637,45 @@ my $json = JSON->new->utf8;
like( $attachments->[4]->Content, qr/IHDR/, "Looks like a PNG image" );
}
+# Ticket Creation - with custom field uploads, using multipart/form-data
+{
+ my $image_cf = RT::Test->load_or_create_custom_field( Name => 'Image', Queue => 'General', Type => 'Image' );
+ $user->PrincipalObj->GrantRight( Right => $_ ) for qw/SeeCustomField ModifyCustomField/;
+
+ my $img_name = 'image.png';
+ my $img_path = RT::Test::get_relocatable_file( $img_name, 'data' );
+ my $img_content = do {
+ local $/;
+ open my $fh, '<', $img_path or die $!;
+ <$fh>;
+ };
+
+ my $payload = {
+ Subject => 'Ticket creation using REST, multipart/form-data, with custom field uploads',
+ Queue => 'General',
+ Content => 'Testing ticket creation, multipart/form-data, with custom field uploads using REST API.',
+ CustomFields => { Image => { UploadField => 'image' } },
+ };
+
+ my $res = $mech->post(
+ "$rest_base_path/ticket",
+ $payload,
+ 'Authorization' => $auth,
+ 'Content_Type' => 'form-data',
+ 'Content' => [
+ 'JSON' => $json->encode($payload),
+ 'image' => [ $img_path, $img_name, 'image/png' ],
+ ],
+ );
+ is( $res->code, 201 );
+ ok( $ticket_url = $res->header('location') );
+ ok( ($ticket_id) = $ticket_url =~ qr[/ticket/(\d+)] );
+
+ my $ticket = RT::Ticket->new($user);
+ $ticket->Load($ticket_id);
+ my $value = $ticket->CustomFieldValues( $image_cf )->First;
+ is( $value->Content, 'image.png', 'image file name');
+ is( $value->LargeContent, $img_content, 'image file content');
+}
+
done_testing;
commit 2bbdbb13d79b13229adcd093d1bb66bbb24e0d74
Merge: 5af84f496f 31b619d5aa
Author: Jim Brandt <jbrandt at bestpractical.com>
Date: Fri Jan 8 11:49:02 2021 -0500
Merge branch '5.0/rest2-support-attachments-when-creating-ticket' into 5.0-trunk
diff --cc lib/RT/REST2/Util.pm
index eba3d8302e,dc2bf92b81..172450afc2
--- a/lib/RT/REST2/Util.pm
+++ b/lib/RT/REST2/Util.pm
@@@ -221,9 -217,8 +222,9 @@@ sub deserialize_record
# Sanitize input for the Perl API
for my $field (sort keys %$data) {
- my $skip_regex = join '|', 'CustomFields',
- next if $field eq 'CustomFields';
- next if $field eq 'Attachments';
++ my $skip_regex = join '|', 'CustomFields', 'Attachments',
+ $record->DOES("RT::Record::Role::Links") ? ( sort keys %RT::Link::TYPEMAP ) : ();
+ next if $field =~ /$skip_regex/;
my $value = $data->{$field};
next unless ref $value;
-----------------------------------------------------------------------
More information about the rt-commit
mailing list