Bugzilla – Attachment 145509 Details for
Bug 31800
Add POST endpoint for Biblios
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 31800: Add REST endpoint to add a biblio
Bug-31800-Add-REST-endpoint-to-add-a-biblio.patch (text/plain), 18.54 KB, created by
Jan Kissig
on 2023-01-20 12:54:37 UTC
(
hide
)
Description:
Bug 31800: Add REST endpoint to add a biblio
Filename:
MIME Type:
Creator:
Jan Kissig
Created:
2023-01-20 12:54:37 UTC
Size:
18.54 KB
patch
obsolete
>From 009e40767788e07a5028e7f409a6b25080fbde7a Mon Sep 17 00:00:00 2001 >From: Agustin Moyano <agustinmoyano@theke.io> >Date: Fri, 23 Dec 2022 17:15:29 -0300 >Subject: [PATCH] Bug 31800: Add REST endpoint to add a biblio > >To test: >1. Apply patch >2. Set RESTBasicAuth preference to true >3. Make a POST request to /api/v1/biblios with one of the following content type header > - application/marcxml+xml > - application/marc-in-json > - application/marc >4. Add the following header to the request: "x-framework-id: <framework id>" >5. Check that the biblio is created >6. Sign off > >Signed-off-by: Jan Kissig <jkissig@th-wildau.de> >--- > Koha/REST/V1/Biblios.pm | 63 ++++- > api/v1/swagger/paths/biblios.yaml | 57 ++++ > api/v1/swagger/swagger.yaml | 24 ++ > t/db_dependent/api/v1/biblios.t | 431 +++++++++++++++++++++++++++++- > 4 files changed, 573 insertions(+), 2 deletions(-) > >diff --git a/Koha/REST/V1/Biblios.pm b/Koha/REST/V1/Biblios.pm >index f923255cfa..4f58a4001b 100644 >--- a/Koha/REST/V1/Biblios.pm >+++ b/Koha/REST/V1/Biblios.pm >@@ -22,7 +22,8 @@ use Mojo::Base 'Mojolicious::Controller'; > use Koha::Biblios; > use Koha::Ratings; > use Koha::RecordProcessor; >-use C4::Biblio qw( DelBiblio ); >+use C4::Biblio qw( DelBiblio AddBiblio ); >+use C4::Search qw( FindDuplicate ); > > use List::MoreUtils qw( any ); > use MARC::Record::MiJ; >@@ -480,4 +481,64 @@ sub set_rating { > }; > } > >+=head3 add >+ >+Controller function that handles creating a biblio object >+ >+=cut >+ >+sub add { >+ my $c = shift->openapi->valid_input or return; >+ >+ try { >+ my $body = $c->validation->param('Body'); >+ >+ my $flavour = $c->validation->param('x-marc-schema'); >+ $flavour = C4::Context->preference('marcflavour') unless $flavour; >+ >+ my $record; >+ >+ my $frameworkcode = $c->validation->param('x-framework-id'); >+ if ( $c->req->headers->content_type =~ m/application\/marcxml\+xml/ ) { >+ $record = MARC::Record->new_from_xml( $body, 'UTF-8', $flavour ); >+ } elsif ( $c->req->headers->content_type =~ m/application\/marc-in-json/ ) { >+ $record = MARC::Record->new_from_mij_structure( $body ); >+ } elsif ( $c->req->headers->content_type =~ m/application\/marc/ ) { >+ $record = MARC::Record->new_from_usmarc( $body ); >+ } else { >+ return $c->render( >+ status => 406, >+ openapi => [ >+ "application/marcxml+xml", >+ "application/marc-in-json", >+ "application/marc" >+ ] >+ ); >+ } >+ >+ my ( $duplicatebiblionumber, $duplicatetitle ); >+ ( $duplicatebiblionumber, $duplicatetitle ) = FindDuplicate($record); >+ >+ my $confirm_not_duplicate = $c->validation->param('x-confirm-not-duplicate'); >+ >+ return $c->render( >+ status => 400, >+ openapi => { >+ error => "Duplicate biblio $duplicatebiblionumber" >+ } >+ ) unless !$duplicatebiblionumber || $confirm_not_duplicate; >+ >+ my ( $biblionumber, $oldbibitemnum ); >+ ( $biblionumber, $oldbibitemnum ) = AddBiblio( $record, $frameworkcode ); >+ >+ $c->render( >+ status => 200, >+ openapi => { id => $biblionumber } >+ ); >+ } >+ catch { >+ $c->unhandled_exception($_); >+ }; >+} >+ > 1; >diff --git a/api/v1/swagger/paths/biblios.yaml b/api/v1/swagger/paths/biblios.yaml >index 782de211e7..c19ec73380 100644 >--- a/api/v1/swagger/paths/biblios.yaml >+++ b/api/v1/swagger/paths/biblios.yaml >@@ -1,4 +1,61 @@ > --- >+"/biblios": >+ post: >+ x-mojo-to: Biblios#add >+ operationId: addBiblio >+ tags: >+ - biblios >+ summary: Add biblio >+ parameters: >+ - name: Body >+ in: body >+ description: A JSON object or the Marc string describing a biblio >+ required: true >+ schema: >+ type: >+ - string >+ - object >+ - $ref: "../swagger.yaml#/parameters/framework_id_header" >+ - $ref: "../swagger.yaml#/parameters/marc_schema_header" >+ - $ref: "../swagger.yaml#/parameters/confirm_not_duplicate_header" >+ produces: >+ - application/json >+ responses: >+ "200": >+ description: A biblio >+ "400": >+ description: Bad request >+ schema: >+ $ref: "../swagger.yaml#/definitions/error" >+ "401": >+ description: Authentication required >+ schema: >+ $ref: "../swagger.yaml#/definitions/error" >+ "403": >+ description: Access forbidden >+ schema: >+ $ref: "../swagger.yaml#/definitions/error" >+ "406": >+ description: Not acceptable >+ schema: >+ type: array >+ description: Accepted content-types >+ items: >+ type: string >+ "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: >+ editcatalogue: edit_catalogue > "/biblios/{biblio_id}": > get: > x-mojo-to: Biblios#get >diff --git a/api/v1/swagger/swagger.yaml b/api/v1/swagger/swagger.yaml >index 696a73be8b..a6515b0e6f 100644 >--- a/api/v1/swagger/swagger.yaml >+++ b/api/v1/swagger/swagger.yaml >@@ -137,6 +137,8 @@ paths: > $ref: paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id}~1domains > "/auth/identity_providers/{identity_provider_id}/domains/{identity_provider_domain_id}": > $ref: paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id}~1domains~1{identity_provider_domain_id} >+ "/biblios": >+ $ref: "./paths/biblios.yaml#/~1biblios" > "/biblios/{biblio_id}": > $ref: "./paths/biblios.yaml#/~1biblios~1{biblio_id}" > "/biblios/{biblio_id}/checkouts": >@@ -336,6 +338,28 @@ parameters: > name: agreement_period_id > required: true > type: integer >+ framework_id_header: >+ description: Framework id. Use when content type is not application/json >+ name: x-framework-id >+ in: header >+ required: false >+ type: string >+ marc_schema_header: >+ description: March schema. One of MARC21 or UNIMARC >+ name: x-marc-schema >+ in: header >+ required: false >+ type: string >+ enum: >+ - MARC21 >+ - UNIMARC >+ confirm_not_duplicate_header: >+ description: Confirm the posted element is not a duplicate >+ name: x-confirm-not-duplicate >+ in: header >+ required: false >+ type: integer >+ > identity_provider_id_pp: > description: Authentication provider internal identifier > in: path >diff --git a/t/db_dependent/api/v1/biblios.t b/t/db_dependent/api/v1/biblios.t >index b4e98b17f4..c5909eece2 100755 >--- a/t/db_dependent/api/v1/biblios.t >+++ b/t/db_dependent/api/v1/biblios.t >@@ -20,7 +20,7 @@ use Modern::Perl; > use utf8; > use Encode; > >-use Test::More tests => 8; >+use Test::More tests => 9; > use Test::MockModule; > use Test::Mojo; > use Test::Warn; >@@ -713,3 +713,432 @@ subtest 'set_rating() tests' => sub { > $schema->storage->txn_rollback; > > }; >+ >+ >+subtest 'post() tests' => sub { >+ >+ plan tests => 13; >+ >+ $schema->storage->txn_begin; >+ >+ my $patron = $builder->build_object( >+ { >+ class => 'Koha::Patrons', >+ value => { flags => 0 } # no permissions >+ } >+ ); >+ my $password = 'thePassword123'; >+ $patron->set_password( { password => $password, skip_validation => 1 } ); >+ my $userid = $patron->userid; >+ >+ my $frameworkcode = 'BKS'; >+ my $marcxml = q|<?xml version="1.0" encoding="UTF-8"?> >+<record >+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >+ xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd" >+ xmlns="http://www.loc.gov/MARC21/slim"> >+ >+ <leader>01102pam a2200289 a 7500</leader> >+ <controlfield tag="001">2504398</controlfield> >+ <controlfield tag="005">20200421093816.0</controlfield> >+ <controlfield tag="008">920610s1993 caub s001 0 eng </controlfield> >+ <datafield tag="010" ind1=" " ind2=" "> >+ <subfield code="a"> 92021731 </subfield> >+ </datafield> >+ <datafield tag="020" ind1=" " ind2=" "> >+ <subfield code="a">05200784381 (Test marcxml)</subfield> >+ </datafield> >+ <datafield tag="020" ind1=" " ind2=" "> >+ <subfield code="a">05200784461 (Test marcxml)</subfield> >+ </datafield> >+ <datafield tag="040" ind1=" " ind2=" "> >+ <subfield code="a">DLC</subfield> >+ <subfield code="c">DLC</subfield> >+ <subfield code="d">DLC</subfield> >+ </datafield> >+ <datafield tag="041" ind1="0" ind2=" "> >+ <subfield code="a">enggrc</subfield> >+ </datafield> >+ <datafield tag="050" ind1="0" ind2="0"> >+ <subfield code="a">PA522</subfield> >+ <subfield code="b">.M38 1993</subfield> >+ </datafield> >+ <datafield tag="082" ind1="0" ind2="0"> >+ <subfield code="a">480</subfield> >+ <subfield code="2">20</subfield> >+ </datafield> >+ <datafield tag="100" ind1="1" ind2=" "> >+ <subfield code="a">Mastronarde, Donald J.</subfield> >+ <subfield code="9">389</subfield> >+ </datafield> >+ <datafield tag="245" ind1="1" ind2="0"> >+ <subfield code="a">Introduction to Attic Greek (Using marcxml) /</subfield> >+ <subfield code="c">Donald J. Mastronarde.</subfield> >+ </datafield> >+ <datafield tag="260" ind1=" " ind2=" "> >+ <subfield code="a">Berkeley :</subfield> >+ <subfield code="b">University of California Press,</subfield> >+ <subfield code="c">c1993.</subfield> >+ </datafield> >+ <datafield tag="300" ind1=" " ind2=" "> >+ <subfield code="a">ix, 425 p. :</subfield> >+ <subfield code="b">maps ;</subfield> >+ <subfield code="c">26 cm.</subfield> >+ </datafield> >+ <datafield tag="500" ind1=" " ind2=" "> >+ <subfield code="a">Includes index.</subfield> >+ </datafield> >+ <datafield tag="650" ind1=" " ind2="0"> >+ <subfield code="a">Attic Greek dialect</subfield> >+ <subfield code="9">7</subfield> >+ </datafield> >+ <datafield tag="856" ind1="4" ind2="2"> >+ <subfield code="3">Contributor biographical information</subfield> >+ <subfield code="u">http://www.loc.gov/catdir/bios/ucal051/92021731.html</subfield> >+ </datafield> >+ <datafield tag="856" ind1="4" ind2="2"> >+ <subfield code="3">Publisher description</subfield> >+ <subfield code="u">http://www.loc.gov/catdir/description/ucal041/92021731.html</subfield> >+ </datafield> >+ <datafield tag="906" ind1=" " ind2=" "> >+ <subfield code="a">7</subfield> >+ <subfield code="b">cbc</subfield> >+ <subfield code="c">orignew</subfield> >+ <subfield code="d">1</subfield> >+ <subfield code="e">ocip</subfield> >+ <subfield code="f">19</subfield> >+ <subfield code="g">y-gencatlg</subfield> >+ </datafield> >+ <datafield tag="942" ind1=" " ind2=" "> >+ <subfield code="2">ddc</subfield> >+ <subfield code="c">BK</subfield> >+ </datafield> >+ <datafield tag="955" ind1=" " ind2=" "> >+ <subfield code="a">pc05 to ea00 06-11-92; ea04 to SCD 06-11-92; fd11 06-11-92 (PA522.M...); fr21 06-12-92; fs62 06-15-92; CIP ver. pv07 11-12-93</subfield> >+ </datafield> >+ <datafield tag="999" ind1=" " ind2=" "> >+ <subfield code="c">3</subfield> >+ <subfield code="d">3</subfield> >+ </datafield> >+</record>|; >+ >+ my $mij = q|{ >+ "fields": [ >+ { >+ "001": "2504398" >+ }, >+ { >+ "005": "20200421093816.0" >+ }, >+ { >+ "008": "920610s1993 caub s001 0 eng " >+ }, >+ { >+ "010": { >+ "ind1": " ", >+ "subfields": [ >+ { >+ "a": " 92021731 " >+ } >+ ], >+ "ind2": " " >+ } >+ }, >+ { >+ "020": { >+ "subfields": [ >+ { >+ "a": "05200784382 (Test mij)" >+ } >+ ], >+ "ind2": " ", >+ "ind1": " " >+ } >+ }, >+ { >+ "020": { >+ "subfields": [ >+ { >+ "a": "05200784462 (Test mij)" >+ } >+ ], >+ "ind1": " ", >+ "ind2": " " >+ } >+ }, >+ { >+ "040": { >+ "subfields": [ >+ { >+ "a": "DLC" >+ }, >+ { >+ "c": "DLC" >+ }, >+ { >+ "d": "DLC" >+ } >+ ], >+ "ind2": " ", >+ "ind1": " " >+ } >+ }, >+ { >+ "041": { >+ "ind2": " ", >+ "subfields": [ >+ { >+ "a": "enggrc" >+ } >+ ], >+ "ind1": "0" >+ } >+ }, >+ { >+ "050": { >+ "subfields": [ >+ { >+ "a": "PA522" >+ }, >+ { >+ "b": ".M38 1993" >+ } >+ ], >+ "ind1": "0", >+ "ind2": "0" >+ } >+ }, >+ { >+ "082": { >+ "subfields": [ >+ { >+ "a": "480" >+ }, >+ { >+ "2": "20" >+ } >+ ], >+ "ind2": "0", >+ "ind1": "0" >+ } >+ }, >+ { >+ "100": { >+ "ind2": " ", >+ "subfields": [ >+ { >+ "a": "Mastronarde, Donald J." >+ }, >+ { >+ "9": "389" >+ } >+ ], >+ "ind1": "1" >+ } >+ }, >+ { >+ "245": { >+ "ind1": "1", >+ "subfields": [ >+ { >+ "a": "Introduction to Attic Greek (Using mij) /" >+ }, >+ { >+ "c": "Donald J. Mastronarde." >+ } >+ ], >+ "ind2": "0" >+ } >+ }, >+ { >+ "260": { >+ "subfields": [ >+ { >+ "a": "Berkeley :" >+ }, >+ { >+ "b": "University of California Press," >+ }, >+ { >+ "c": "c1993." >+ } >+ ], >+ "ind2": " ", >+ "ind1": " " >+ } >+ }, >+ { >+ "300": { >+ "ind1": " ", >+ "subfields": [ >+ { >+ "a": "ix, 425 p. :" >+ }, >+ { >+ "b": "maps ;" >+ }, >+ { >+ "c": "26 cm." >+ } >+ ], >+ "ind2": " " >+ } >+ }, >+ { >+ "500": { >+ "subfields": [ >+ { >+ "a": "Includes index." >+ } >+ ], >+ "ind1": " ", >+ "ind2": " " >+ } >+ }, >+ { >+ "650": { >+ "subfields": [ >+ { >+ "a": "Attic Greek dialect" >+ }, >+ { >+ "9": "7" >+ } >+ ], >+ "ind2": "0", >+ "ind1": " " >+ } >+ }, >+ { >+ "856": { >+ "subfields": [ >+ { >+ "3": "Contributor biographical information" >+ }, >+ { >+ "u": "http://www.loc.gov/catdir/bios/ucal051/92021731.html" >+ } >+ ], >+ "ind2": "2", >+ "ind1": "4" >+ } >+ }, >+ { >+ "856": { >+ "ind1": "4", >+ "subfields": [ >+ { >+ "3": "Publisher description" >+ }, >+ { >+ "u": "http://www.loc.gov/catdir/description/ucal041/92021731.html" >+ } >+ ], >+ "ind2": "2" >+ } >+ }, >+ { >+ "906": { >+ "subfields": [ >+ { >+ "a": "7" >+ }, >+ { >+ "b": "cbc" >+ }, >+ { >+ "c": "orignew" >+ }, >+ { >+ "d": "1" >+ }, >+ { >+ "e": "ocip" >+ }, >+ { >+ "f": "19" >+ }, >+ { >+ "g": "y-gencatlg" >+ } >+ ], >+ "ind1": " ", >+ "ind2": " " >+ } >+ }, >+ { >+ "942": { >+ "subfields": [ >+ { >+ "2": "ddc" >+ }, >+ { >+ "c": "BK" >+ } >+ ], >+ "ind2": " ", >+ "ind1": " " >+ } >+ }, >+ { >+ "955": { >+ "subfields": [ >+ { >+ "a": "pc05 to ea00 06-11-92; ea04 to SCD 06-11-92; fd11 06-11-92 (PA522.M...); fr21 06-12-92; fs62 06-15-92; CIP ver. pv07 11-12-93" >+ } >+ ], >+ "ind2": " ", >+ "ind1": " " >+ } >+ }, >+ { >+ "999": { >+ "subfields": [ >+ { >+ "c": "3" >+ }, >+ { >+ "d": "3" >+ } >+ ], >+ "ind1": " ", >+ "ind2": " " >+ } >+ } >+ ], >+ "leader": "01102pam a2200289 a 8500" >+}|; >+ my $marc = q|01102pam a2200289 a 9500001000800000005001700008008004100025010001700066020002800083020003500111040001800146041001100164050002100175082001200196100003200208245005800240260005600298300003300354500002000387650002700407856009500434856008700529906004500616942001200661955013000673999000900803250439820200421093816.0920610s1993 caub s001 0 eng a 92021731 a05200784383 (Test usmarc) a05200784463 (Test usmarc) aDLCcDLCdDLC0 aenggrc00aPA522b.M38 199300a4802201 aMastronarde, Donald J.938910aIntroduction to Attic Greek (Using usmarc) /cDonald J. Mastronarde. aBerkeley :bUniversity of California Press,cc1993. aix, 425 p. :bmaps ;c26 cm. aIncludes index. 0aAttic Greek dialect97423Contributor biographical informationuhttp://www.loc.gov/catdir/bios/ucal051/92021731.html423Publisher descriptionuhttp://www.loc.gov/catdir/description/ucal041/92021731.html a7bcbccorignewd1eocipf19gy-gencatlg 2ddccBK apc05 to ea00 06-11-92; ea04 to SCD 06-11-92; fd11 06-11-92 (PA522.M...); fr21 06-12-92; fs62 06-15-92; CIP ver. pv07 11-12-93 c3d3|; >+ >+ $t->post_ok("//$userid:$password@/api/v1/biblios") >+ ->status_is(403, 'Not enough permissions makes it return the right code'); >+ >+ # Add permissions >+ $builder->build( >+ { >+ source => 'UserPermission', >+ value => { >+ borrowernumber => $patron->borrowernumber, >+ module_bit => 9, >+ code => 'edit_catalogue' >+ } >+ } >+ ); >+ >+ $t->post_ok("//$userid:$password@/api/v1/biblios" => {'Content-Type' => 'application/marcxml+xml', 'x-framework-id' => $frameworkcode, "x-march-schema" => 'INVALID'}) >+ ->status_is(400, 'Invalid header x-marc-schema'); >+ >+ $t->post_ok("//$userid:$password@/api/v1/biblios" => {'Content-Type' => 'application/marcxml+xml', 'x-framework-id' => $frameworkcode} => $marcxml) >+ ->status_is(200) >+ ->json_has('/id'); >+ >+ $t->post_ok("//$userid:$password@/api/v1/biblios" => {'Content-Type' => 'application/marc-in-json', 'x-framework-id' => $frameworkcode, 'x-confirm-not-duplicate' => 1} => $mij) >+ ->status_is(200) >+ ->json_has('/id'); >+ >+ $t->post_ok("//$userid:$password@/api/v1/biblios" => {'Content-Type' => 'application/marc', 'x-framework-id' => $frameworkcode} => $marc) >+ ->status_is(200) >+ ->json_has('/id'); >+ >+ $schema->storage->txn_rollback; >+}; >\ No newline at end of file >-- >2.30.2
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 31800
:
144830
|
144835
|
144837
|
145509
|
147714