[Rt-commit] rt branch, 5.0/rest2-efficiently-get-ticket-attachment-list, created. rt-5.0.0-53-gac085f9cd4

Dianne Skoll dianne at bestpractical.com
Fri Oct 16 14:53:15 EDT 2020


The branch, 5.0/rest2-efficiently-get-ticket-attachment-list has been created
        at  ac085f9cd432e062dc328b7be5ca675aeaf12382 (commit)

- Log -----------------------------------------------------------------
commit ac085f9cd432e062dc328b7be5ca675aeaf12382
Author: Dianne Skoll <dianne at bestpractical.com>
Date:   Fri Oct 16 14:50:57 2020 -0400

    Add the REST2 endpoint: GET /ticket/:id/attachments?field=F1,F2,...,Fn
    
    This endpoint returns a list of attachments associated with a ticket; the
    "fields" query parameter lets you select which fields to return for each
    attachment.
    
    This endpoint only returns non-empty attachments; as such, it won't return
    multipart wrappers.

diff --git a/lib/RT/REST2.pm b/lib/RT/REST2.pm
index 1079f95cd6..5f9bf1ba9d 100644
--- a/lib/RT/REST2.pm
+++ b/lib/RT/REST2.pm
@@ -557,6 +557,9 @@ Below are some examples using the endpoints above.
     GET /transaction/:id/attachments
         get attachments for transaction
 
+    GET /ticket/:id/attachments
+        get attachments associated with a ticket
+
     GET /attachment/:id
         retrieve an attachment
 
diff --git a/lib/RT/REST2/Resource/Attachments.pm b/lib/RT/REST2/Resource/Attachments.pm
index d098aaa01a..c7751683b8 100644
--- a/lib/RT/REST2/Resource/Attachments.pm
+++ b/lib/RT/REST2/Resource/Attachments.pm
@@ -69,7 +69,38 @@ sub dispatch_rules {
             $txn->Load($match->pos(1));
             return { collection => $txn->Attachments };
         },
-    )
+    ),
+    Path::Dispatcher::Rule::Regex->new(
+        regex => qr{^/ticket/(\d+)/attachments/?$},
+        block => sub {
+            my ($match, $req) = @_;
+            return _get_ticket_attachments($match, $req);
+        },
+    ),
+}
+
+# Get a collection of non-empty attachments associated with a ticket
+# This code was put into a subroutine as it was a little long to
+# put inline above and maintain readability.
+sub _get_ticket_attachments
+{
+    my ($match, $req) = @_;
+
+    my $ticket = RT::Ticket->new($req->env->{"rt.current_user"});
+    my $id = $ticket->Load($match->pos(1));
+    my $attachments = RT::Attachments->new($req->env->{"rt.current_user"});
+
+    # Return empty list if no such ticket
+    return { collection => $attachments } unless $id;
+
+    # Explicitly check for permission to see the ticket.
+    # If we do not do that, we leak the total number of attachments
+    # even though the actual attachments themselves are not shown.
+    return { collection => $attachments } unless $ticket->CurrentUserHasRight('ShowTicket');
+
+    $attachments->LimitByTicket($id);
+    $attachments->LimitNotEmpty();
+    return { collection => $attachments };
 }
 
 __PACKAGE__->meta->make_immutable;
diff --git a/t/rest2/attachments.t b/t/rest2/attachments.t
index d7aa05fac7..09e5ff9ef0 100644
--- a/t/rest2/attachments.t
+++ b/t/rest2/attachments.t
@@ -98,6 +98,43 @@ $image_content = MIME::Base64::encode_base64($image_content);
     ok(!$attachments->[3]->Subject);
 }
 
+# Check the GET /ticket/:id/attachments endpoint
+{
+    my $res = $mech->get("$rest_base_path/ticket/$ticket_id/attachments?fields=Subject,Filename,ContentType",
+        'Authorization' => $auth);
+    is ($res->code, 200);
+
+    # We get three attachments instead of 4 because the
+    # /ticket/:id/attachments endpoint suppresses empty attachments;
+    # we won't see the multipart/mixed wrapper.
+    cmp_deeply($mech->json_response,
+               { per_page => 20,
+                 pages => 1,
+                 total => 3,
+                 page => 1,
+                 count => 3,
+                 items => [
+                     {type => 'attachment',
+                      Subject => '',
+                      _url => re( qr/^https?:/ ),
+                      ContentType => 'text/html',
+                      Filename => '',
+                      id => re(qr/^\d+$/)},
+                     {type => 'attachment',
+                      Subject => '',
+                      _url => re( qr/^https?:/ ),
+                      ContentType => 'image/png',
+                      Filename => 'image.png',
+                      id => re(qr/^\d+$/)},
+                     {type => 'attachment',
+                      Subject => '',
+                      _url => re( qr/^https?:/ ),
+                      ContentType => 'text/plain',
+                      Filename => 'password',
+                      id => re(qr/^\d+$/)},
+                     ]}, 'Got expected attachment list');
+}
+
 # Comment ticket with image attachment and no content through JSON Base64
 {
     my $payload = {

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


More information about the rt-commit mailing list