Bug 30982: API tweaks
authorTomas Cohen Arazi <tomascohen@theke.io>
Mon, 12 Sep 2022 16:02:25 +0000 (13:02 -0300)
committerTomas Cohen Arazi <tomascohen@theke.io>
Fri, 23 Sep 2022 11:57:49 +0000 (08:57 -0300)
This patch makes the following changes to the 'background_jobs' API:

* We now call them 'jobs'
* Removed deprecated query parameter definitions
* Added only_current query parameter
* Controller gets adapted to use $rs->filter_by_current when
  only_current is passed

Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
Koha/BackgroundJob.pm
Koha/REST/V1/BackgroundJobs.pm
api/v1/swagger/definitions/background_job.yaml [deleted file]
api/v1/swagger/definitions/job.yaml [new file with mode: 0644]
api/v1/swagger/paths/background_jobs.yaml [deleted file]
api/v1/swagger/paths/jobs.yaml [new file with mode: 0644]
api/v1/swagger/swagger.yaml
t/db_dependent/api/v1/background_jobs.t [deleted file]
t/db_dependent/api/v1/jobs.t [new file with mode: 0755]
t/lib/TestBuilder.pm

index c6058c9..df3643a 100644 (file)
@@ -472,6 +472,27 @@ sub plugin_types_to_classes {
     return $self->{_plugin_mapping};
 }
 
+=head3 to_api
+
+    my $json = $job->to_api;
+
+Overloaded method that returns a JSON representation of the Koha::BackgroundJob object,
+suitable for API output.
+
+=cut
+
+sub to_api {
+    my ( $self, $params ) = @_;
+
+    my $json = $self->SUPER::to_api( $params );
+
+    $json->{context} = $self->json->decode($self->context)
+      if defined $self->context;
+    $json->{data} = $self->decoded_data;
+
+    return $json;
+}
+
 =head3 to_api_mapping
 
 This method returns the mapping for representing a Koha::BackgroundJob object
@@ -481,8 +502,11 @@ on the API.
 
 sub to_api_mapping {
     return {
-        id             => 'background_job_id',
+        id             => 'job_id',
         borrowernumber => 'patron_id',
+        ended_on       => 'ended_date',
+        enqueued_on    => 'enqueued_date',
+        started_on     => 'started_date',
     };
 }
 
index 251d565..cb1543d 100644 (file)
@@ -29,49 +29,66 @@ use Try::Tiny;
 
 =head3 list
 
+Controller function that handles listing Koha::BackgrounJob objects
+
 =cut
 
 sub list {
     my $c = shift->openapi->valid_input or return;
 
     return try {
-        my $background_jobs_set = Koha::BackgroundJobs->new;
-        my $background_jobs     = $c->objects->search($background_jobs_set);
-        return $c->render( status => 200, openapi => $background_jobs );
-    }
-    catch {
+
+        my $only_current = delete $c->validation->output->{only_current};
+
+        my $bj_rs = Koha::BackgroundJobs->new;
+
+        if ($only_current) {
+            $bj_rs = $bj_rs->filter_by_current;
+        }
+
+        return $c->render(
+            status  => 200,
+            openapi => $c->objects->search($bj_rs)
+        );
+    } catch {
         $c->unhandled_exception($_);
     };
 }
 
+=head3 get
+
+Controller function that handles retrieving a single Koha::BackgroundJob object
+
+=cut
+
 sub get {
     my $c = shift->openapi->valid_input or return;
 
     return try {
 
-        my $background_job_id = $c->validation->param('background_job_id');
-        my $patron            = $c->stash('koha.user');
+        my $job_id = $c->validation->param('job_id');
+        my $patron = $c->stash('koha.user');
 
         my $can_manage_background_jobs =
           $patron->has_permission( { parameters => 'manage_background_jobs' } );
 
-        my $background_job = Koha::BackgroundJobs->find($background_job_id);
+        my $job = Koha::BackgroundJobs->find($job_id);
 
         return $c->render(
             status  => 404,
             openapi => { error => "Object not found" }
-        ) unless $background_job;
+        ) unless $job;
 
         return $c->render(
             status  => 403,
             openapi => { error => "Cannot see background job info" }
           )
           if !$can_manage_background_jobs
-          && $background_job->borrowernumber != $patron->borrowernumber;
+          && $job->borrowernumber != $patron->borrowernumber;
 
         return $c->render(
             status  => 200,
-            openapi => $background_job->to_api
+            openapi => $job->to_api
         );
     }
     catch {
diff --git a/api/v1/swagger/definitions/background_job.yaml b/api/v1/swagger/definitions/background_job.yaml
deleted file mode 100644 (file)
index 09cbbe6..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
----
-type: object
-properties:
-  background_job_id:
-    type: integer
-    description: internally assigned background_job identifier
-    readOnly: true
-  status:
-    description: background_job status
-    type:
-      - string
-      - "null"
-  progress:
-    description: background_job progress
-    type:
-      - string
-      - "null"
-  size:
-    description: background_job size
-    type:
-      - string
-      - "null"
-  patron_id:
-    description: background_job enqueuer
-    type:
-      - string
-      - "null"
-  type:
-    description: background_job type
-    type:
-      - string
-      - "null"
-  queue:
-    description: background_job queue
-    type:
-      - string
-      - "null"
-  data:
-    description: background_job data
-    type:
-      - string
-      - "null"
-  context:
-    description: background_job context
-    type:
-      - string
-      - "null"
-  enqueued_on:
-    description: background_job enqueue date
-    type:
-      - string
-      - "null"
-  started_on:
-    description: background_job start date
-    type:
-      - string
-      - "null"
-  ended_on:
-    description: background_job end date
-    type:
-      - string
-      - "null"
-additionalProperties: false
diff --git a/api/v1/swagger/definitions/job.yaml b/api/v1/swagger/definitions/job.yaml
new file mode 100644 (file)
index 0000000..966e3a3
--- /dev/null
@@ -0,0 +1,54 @@
+---
+type: object
+properties:
+  job_id:
+    type: integer
+    description: internally assigned job identifier
+    readOnly: true
+  status:
+    description: job status
+    type: string
+  progress:
+    description: job progress
+    type:
+      - string
+      - "null"
+  size:
+    description: job size
+    type:
+      - string
+      - "null"
+  patron_id:
+    description: job enqueuer
+    type:
+      - string
+      - "null"
+  type:
+    description: job type
+    type: string
+  queue:
+    description: job queue
+    type: string
+  data:
+    description: job data
+    type: object
+  context:
+    description: job context
+    type: object
+  enqueued_date:
+    description: job enqueue date
+    type: string
+    format: date-time
+  started_date:
+    description: job start date
+    type:
+      - string
+      - "null"
+    format: date-time
+  ended_date:
+    description: job end date
+    type:
+      - string
+      - "null"
+    format: date-time
+additionalProperties: false
diff --git a/api/v1/swagger/paths/background_jobs.yaml b/api/v1/swagger/paths/background_jobs.yaml
deleted file mode 100644 (file)
index ecc80a2..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
----
-/background_jobs:
-  get:
-    x-mojo-to: BackgroundJobs#list
-    operationId: listBackgroundJobs
-    tags:
-      - background_jobs
-    summary: List background jobs
-    produces:
-      - application/json
-    parameters:
-      - name: status
-        in: query
-        description: Case insensative search on job status
-        required: false
-        type: string
-      - name: progress
-        in: query
-        description: Case insensative search on job progress
-        required: false
-        type: string
-      - name: size
-        in: query
-        description: Case insensative search on job size
-        required: false
-        type: string
-      - name: patron_id
-        in: query
-        description: Case insensative search on job enqueuer id
-        required: false
-        type: string
-      - name: type
-        in: query
-        description: Case insensative search on job type
-        required: false
-        type: string
-      - name: queue
-        in: query
-        description: Case insensative search on job queue
-        required: false
-        type: string
-      - name: context
-        in: query
-        description: Case insensative search on context
-        required: false
-        type: string
-      - name: enqueued_on
-        in: query
-        description: Case insensative search on job enqueue date
-        required: false
-        type: string
-      - name: started_on
-        in: query
-        description: Case insensative search on job start date
-        required: false
-        type: string
-      - name: ended_on
-        in: query
-        description: Case insensative search on job end date
-        required: false
-        type: string
-      - $ref: "../swagger.yaml#/parameters/match"
-      - $ref: "../swagger.yaml#/parameters/order_by"
-      - $ref: "../swagger.yaml#/parameters/page"
-      - $ref: "../swagger.yaml#/parameters/per_page"
-      - $ref: "../swagger.yaml#/parameters/q_param"
-      - $ref: "../swagger.yaml#/parameters/q_body"
-      - $ref: "../swagger.yaml#/parameters/q_header"
-      - $ref: "../swagger.yaml#/parameters/request_id_header"
-    responses:
-      "200":
-        description: A list of jobs
-        schema:
-          type: array
-          items:
-            $ref: "../swagger.yaml#/definitions/background_job"
-      "403":
-        description: Access forbidden
-        schema:
-          $ref: "../swagger.yaml#/definitions/error"
-      "500":
-        description: |
-          Internal server error. Possible `error_code` attribute values:
-
-          * `internal_server_error`
-        schema:
-          $ref: "../swagger.yaml#/definitions/error"
-      "503":
-        description: Under maintenance
-        schema:
-          $ref: "../swagger.yaml#/definitions/error"
-    x-koha-authorization:
-      permissions:
-        catalogue: "1"
-"/background_jobs/{background_job_id}":
-  get:
-    x-mojo-to: BackgroundJobs#get
-    operationId: getBackgroundJob
-    tags:
-      - background_job
-    summary: Get background job
-    parameters:
-      - $ref: "../swagger.yaml#/parameters/background_job_id_pp"
-    produces:
-      - application/json
-    responses:
-      "200":
-        description: A background job
-        schema:
-          $ref: "../swagger.yaml#/definitions/background_job"
-      "403":
-        description: Access forbidden
-        schema:
-          $ref: "../swagger.yaml#/definitions/error"
-      "404":
-        description: Background job not found
-        schema:
-          $ref: "../swagger.yaml#/definitions/error"
-      "500":
-        description: |
-          Internal server error. Possible `error_code` attribute values:
-
-          * `internal_server_error`
-        schema:
-          $ref: "../swagger.yaml#/definitions/error"
-      "503":
-        description: Under maintenance
-        schema:
-          $ref: "../swagger.yaml#/definitions/error"
-    x-koha-authorization:
-      permissions:
-        catalogue: "1"
diff --git a/api/v1/swagger/paths/jobs.yaml b/api/v1/swagger/paths/jobs.yaml
new file mode 100644 (file)
index 0000000..c7f0f98
--- /dev/null
@@ -0,0 +1,87 @@
+---
+/jobs:
+  get:
+    x-mojo-to: BackgroundJobs#list
+    operationId: listJobs
+    tags:
+      - jobs
+    summary: List jobs
+    produces:
+      - application/json
+    parameters:
+      - name: only_current
+        in: query
+        required: false
+        type: boolean
+        description: If should filter out not current jobs
+      - $ref: "../swagger.yaml#/parameters/match"
+      - $ref: "../swagger.yaml#/parameters/order_by"
+      - $ref: "../swagger.yaml#/parameters/page"
+      - $ref: "../swagger.yaml#/parameters/per_page"
+      - $ref: "../swagger.yaml#/parameters/q_param"
+      - $ref: "../swagger.yaml#/parameters/q_body"
+      - $ref: "../swagger.yaml#/parameters/q_header"
+      - $ref: "../swagger.yaml#/parameters/request_id_header"
+    responses:
+      "200":
+        description: A list of jobs
+        schema:
+          type: array
+          items:
+            $ref: "../swagger.yaml#/definitions/job"
+      "403":
+        description: Access forbidden
+        schema:
+          $ref: "../swagger.yaml#/definitions/error"
+      "500":
+        description: |
+          Internal server error. Possible `error_code` attribute values:
+
+          * `internal_server_error`
+        schema:
+          $ref: "../swagger.yaml#/definitions/error"
+      "503":
+        description: Under maintenance
+        schema:
+          $ref: "../swagger.yaml#/definitions/error"
+    x-koha-authorization:
+      permissions:
+        catalogue: "1"
+"/jobs/{job_id}":
+  get:
+    x-mojo-to: BackgroundJobs#get
+    operationId: getJob
+    tags:
+      - jobs
+    summary: Get a job
+    parameters:
+      - $ref: "../swagger.yaml#/parameters/job_id_pp"
+    produces:
+      - application/json
+    responses:
+      "200":
+        description: A job
+        schema:
+          $ref: "../swagger.yaml#/definitions/job"
+      "403":
+        description: Access forbidden
+        schema:
+          $ref: "../swagger.yaml#/definitions/error"
+      "404":
+        description: Job not found
+        schema:
+          $ref: "../swagger.yaml#/definitions/error"
+      "500":
+        description: |
+          Internal server error. Possible `error_code` attribute values:
+
+          * `internal_server_error`
+        schema:
+          $ref: "../swagger.yaml#/definitions/error"
+      "503":
+        description: Under maintenance
+        schema:
+          $ref: "../swagger.yaml#/definitions/error"
+    x-koha-authorization:
+      permissions:
+        catalogue: "1"
index 3d4be6e..5bdbab2 100644 (file)
@@ -8,8 +8,6 @@ definitions:
     $ref: ./definitions/advancededitormacro.yaml
   allows_renewal:
     $ref: ./definitions/allows_renewal.yaml
-  background_job:
-    $ref: ./definitions/background_job.yaml
   basket:
     $ref: ./definitions/basket.yaml
   bundle_link:
@@ -48,6 +46,8 @@ definitions:
     $ref: ./definitions/item.yaml
   item_group:
     $ref: ./definitions/item_group.yaml
+  job:
+    $ref: ./definitions/job.yaml
   library:
     $ref: ./definitions/library.yaml
   order:
@@ -105,10 +105,6 @@ paths:
     $ref: "./paths/article_requests.yaml#/~1article_requests~1{article_request_id}"
   /auth/otp/token_delivery:
     $ref: paths/auth.yaml#/~1auth~1otp~1token_delivery
-  /background_jobs:
-    $ref: ./paths/background_jobs.yaml#/~1background_jobs
-  "/background_jobs/{background_job_id}":
-    $ref: "./paths/background_jobs.yaml#/~1background_jobs~1{background_job_id}"
   "/biblios/{biblio_id}":
     $ref: "./paths/biblios.yaml#/~1biblios~1{biblio_id}"
   "/biblios/{biblio_id}/checkouts":
@@ -185,6 +181,10 @@ paths:
     $ref: ./paths/items.yaml#/~1items~1{item_id}~1bundled_items~1{bundled_item_id}
   "/items/{item_id}/pickup_locations":
     $ref: "./paths/items.yaml#/~1items~1{item_id}~1pickup_locations"
+  /jobs:
+    $ref: ./paths/jobs.yaml#/~1jobs
+  "/jobs/{job_id}":
+    $ref: "./paths/jobs.yaml#/~1jobs~1{job_id}"
   /libraries:
     $ref: ./paths/libraries.yaml#/~1libraries
   "/libraries/{library_id}":
@@ -260,12 +260,6 @@ parameters:
     name: advancededitormacro_id
     required: true
     type: integer
-  background_job_id_pp:
-    description: Job internal identifier
-    in: path
-    name: background_job_id
-    required: true
-    type: integer
   biblio_id_pp:
     description: Record internal identifier
     in: path
@@ -338,6 +332,12 @@ parameters:
     name: item_id
     required: true
     type: integer
+  job_id_pp:
+    description: Job internal identifier
+    in: path
+    name: job_id
+    required: true
+    type: integer
   library_id_pp:
     description: Internal library identifier
     in: path
@@ -604,6 +604,9 @@ tags:
   - description: "Manage items\n"
     name: items
     x-displayName: Items
+  - description: "Manage jobs\n"
+    name: jobs
+    x-displayName: Jobs
   - description: "Manage libraries\n"
     name: libraries
     x-displayName: Libraries
diff --git a/t/db_dependent/api/v1/background_jobs.t b/t/db_dependent/api/v1/background_jobs.t
deleted file mode 100755 (executable)
index 11181b1..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-#!/usr/bin/env perl
-
-# This file is part of Koha.
-#
-# Koha is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-#
-# Koha 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 Koha; if not, see <http://www.gnu.org/licenses>.
-
-use Modern::Perl;
-
-use Test::More tests => 25;
-use Test::Mojo;
-
-use t::lib::TestBuilder;
-use t::lib::Mocks;
-
-use Koha::BackgroundJobs;
-use Koha::Database;
-
-my $schema  = Koha::Database->new->schema;
-my $builder = t::lib::TestBuilder->new;
-
-my $t = Test::Mojo->new('Koha::REST::V1');
-#use t::lib::Mojo;
-#my $t = t::lib::Mojo->new('Koha::REST::V1');
-t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
-
-$schema->storage->txn_begin;
-
-Koha::BackgroundJobs->delete;
-my $superlibrarian = $builder->build_object(
-    {
-        class => 'Koha::Patrons',
-        value => { flags => 1 },
-    }
-);
-my $password = 'thePassword123';
-$superlibrarian->set_password( { password => $password, skip_validation => 1 } );
-my $superlibrarian_userid = $superlibrarian->userid;
-
-my $librarian = $builder->build_object(
-    {
-        class => 'Koha::Patrons',
-        value => { flags => 2 ** 2 }, # catalogue flag = 2
-    }
-);
-$librarian->set_password( { password => $password, skip_validation => 1 } );
-my $librarian_userid = $librarian->userid;
-
-my $patron = $builder->build_object(
-    {
-        class => 'Koha::Patrons',
-        value => { flags => 0 },
-    }
-);
-$patron->set_password( { password => $password, skip_validation => 1 } );
-my $patron_userid = $patron->userid;
-
-$t->get_ok("//$librarian_userid:$password@/api/v1/background_jobs")
-  ->status_is(200)
-  ->json_is( [] );
-
-my $background_job = $builder->build_object(
-    {
-        class => 'Koha::BackgroundJobs',
-        value => {
-            status         => 'finished',
-            progress       => 100,
-            size           => 100,
-            borrowernumber => $patron->borrowernumber,
-            type           => 'batch_item_record_modification',
-            queue => 'default',
-            #data => '{"record_ids":["1"],"regex_mod":null,"exclude_from_local_holds_priority":null,"new_values":{"itemnotes":"xxx"}}' ,
-            data => '{"regex_mod":null,"report":{"total_records":1,"modified_fields":1,"modified_itemnumbers":[1]},"new_values":{"itemnotes":"xxx"},"record_ids":["1"],"exclude_from_local_holds_priority":null}',
-        }
-    }
-);
-
-{
-    $t->get_ok("//$superlibrarian_userid:$password@/api/v1/background_jobs")
-      ->status_is(200)->json_is( [ $background_job->to_api ] );
-
-    $t->get_ok("//$librarian_userid:$password@/api/v1/background_jobs")
-      ->status_is(200)->json_is( [] );
-
-    $t->get_ok("//$patron_userid:$password@/api/v1/background_jobs")
-      ->status_is(403);
-
-    $background_job->borrowernumber( $librarian->borrowernumber )->store;
-
-    $t->get_ok("//$librarian_userid:$password@/api/v1/background_jobs")
-      ->status_is(200)->json_is( [ $background_job->to_api ] );
-}
-
-{
-    $t->get_ok( "//$superlibrarian_userid:$password@/api/v1/background_jobs/"
-          . $background_job->id )->status_is(200)
-      ->json_is( $background_job->to_api );
-
-    $t->get_ok( "//$librarian_userid:$password@/api/v1/background_jobs/"
-          . $background_job->id )->status_is(200)
-      ->json_is( $background_job->to_api );
-
-    $background_job->borrowernumber( $superlibrarian->borrowernumber )->store;
-    $t->get_ok( "//$librarian_userid:$password@/api/v1/background_jobs/"
-          . $background_job->id )->status_is(403);
-}
-
-{
-    $background_job->delete;
-    $t->get_ok( "//$superlibrarian_userid:$password@/api/v1/background_jobs/"
-          . $background_job->id )->status_is(404)
-      ->json_is( '/error' => 'Object not found' );
-}
-
-$schema->storage->txn_rollback;
diff --git a/t/db_dependent/api/v1/jobs.t b/t/db_dependent/api/v1/jobs.t
new file mode 100755 (executable)
index 0000000..4d993c6
--- /dev/null
@@ -0,0 +1,125 @@
+#!/usr/bin/env perl
+
+# This file is part of Koha.
+#
+# Koha is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# Koha 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 Koha; if not, see <http://www.gnu.org/licenses>.
+
+use Modern::Perl;
+
+use Test::More tests => 25;
+use Test::Mojo;
+
+use t::lib::TestBuilder;
+use t::lib::Mocks;
+
+use Koha::BackgroundJobs;
+use Koha::Database;
+
+my $schema  = Koha::Database->new->schema;
+my $builder = t::lib::TestBuilder->new;
+
+my $t = Test::Mojo->new('Koha::REST::V1');
+#use t::lib::Mojo;
+#my $t = t::lib::Mojo->new('Koha::REST::V1');
+t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
+
+$schema->storage->txn_begin;
+
+Koha::BackgroundJobs->delete;
+my $superlibrarian = $builder->build_object(
+    {
+        class => 'Koha::Patrons',
+        value => { flags => 1 },
+    }
+);
+my $password = 'thePassword123';
+$superlibrarian->set_password( { password => $password, skip_validation => 1 } );
+my $superlibrarian_userid = $superlibrarian->userid;
+
+my $librarian = $builder->build_object(
+    {
+        class => 'Koha::Patrons',
+        value => { flags => 2 ** 2 }, # catalogue flag = 2
+    }
+);
+$librarian->set_password( { password => $password, skip_validation => 1 } );
+my $librarian_userid = $librarian->userid;
+
+my $patron = $builder->build_object(
+    {
+        class => 'Koha::Patrons',
+        value => { flags => 0 },
+    }
+);
+$patron->set_password( { password => $password, skip_validation => 1 } );
+my $patron_userid = $patron->userid;
+
+$t->get_ok("//$librarian_userid:$password@/api/v1/jobs")
+  ->status_is(200)
+  ->json_is( [] );
+
+my $job = $builder->build_object(
+    {
+        class => 'Koha::BackgroundJobs',
+        value => {
+            status         => 'finished',
+            progress       => 100,
+            size           => 100,
+            borrowernumber => $patron->borrowernumber,
+            type           => 'batch_item_record_modification',
+            queue => 'default',
+            #data => '{"record_ids":["1"],"regex_mod":null,"exclude_from_local_holds_priority":null,"new_values":{"itemnotes":"xxx"}}' ,
+            data => '{"regex_mod":null,"report":{"total_records":1,"modified_fields":1,"modified_itemnumbers":[1]},"new_values":{"itemnotes":"xxx"},"record_ids":["1"],"exclude_from_local_holds_priority":null}',
+        }
+    }
+);
+
+{
+    $t->get_ok("//$superlibrarian_userid:$password@/api/v1/jobs")
+      ->status_is(200)->json_is( [ $job->to_api ] );
+
+    $t->get_ok("//$librarian_userid:$password@/api/v1/jobs")
+      ->status_is(200)->json_is( [] );
+
+    $t->get_ok("//$patron_userid:$password@/api/v1/jobs")
+      ->status_is(403);
+
+    $job->borrowernumber( $librarian->borrowernumber )->store;
+
+    $t->get_ok("//$librarian_userid:$password@/api/v1/jobs")
+      ->status_is(200)->json_is( [ $job->to_api ] );
+}
+
+{
+    $t->get_ok( "//$superlibrarian_userid:$password@/api/v1/jobs/"
+          . $job->id )->status_is(200)
+      ->json_is( $job->to_api );
+
+    $t->get_ok( "//$librarian_userid:$password@/api/v1/jobs/"
+          . $job->id )->status_is(200)
+      ->json_is( $job->to_api );
+
+    $job->borrowernumber( $superlibrarian->borrowernumber )->store;
+    $t->get_ok( "//$librarian_userid:$password@/api/v1/jobs/"
+          . $job->id )->status_is(403);
+}
+
+{
+    $job->delete;
+    $t->get_ok( "//$superlibrarian_userid:$password@/api/v1/jobs/"
+          . $job->id )->status_is(404)
+      ->json_is( '/error' => 'Object not found' );
+}
+
+$schema->storage->txn_rollback;
index 59ba592..d6e88e7 100644 (file)
@@ -558,6 +558,9 @@ sub _gen_blob {
 sub _gen_default_values {
     my ($self) = @_;
     return {
+        BackgroundJob => {
+            context => '{}'
+        },
         Borrower => {
             login_attempts => 0,
             gonenoaddress  => undef,