Bug 35380: Make updateBiblio-API respect Record overlay rules

This patch moves hardcoded source filter from 'MARC overlay rules' (batchmod, intranet, z3950, staged import, bulk import, import_lexile) to 'Record Sources' and makes them untouchable. They cannot be renamed or modified.
New record sources can be added and modified though.
All default and newly created record sources are available as filter for the module "Source" in 'MARC overlay rules'.
The API route for PUT /biblios/:biblio_id now checks for a given header x-record-source-id.
If an id is given the name of the rule is retrieved and forwarded as an overlay_context to ModBiblio.
If no id is given the fallback '*' is added as overlay_context.
Also the record source id is getting saved.

Test plan:
pre) run perl installer/data/mysql/updatedatabase.pl to add new is_system column
pre) run dbic to build Koha::Schema::Result::RecordSource as it gets a new columns is_system
pre) run 'redocly bundle --ext json api/v1/swagger/swagger.yaml --output api/v1/swagger/swagger_bundle.json' or 'yarn build'

a) enable system preference MARCOverlayRules and RESTBasicAuth
b) create new record source in /cgi-bin/koha/admin/record_sources and recognize its <NAME> and <ID>
c) create overlay rules in /cgi-bin/koha/admin/marc-overlay-rules.pl
f.e.
+----+-----+--------+----------+-----------+
| id | tag | module | filter   | preset    |
+----+-----+--------+----------+-----------+
|  1 | 245 | source | *        | protect   |
+----+-----+--------+----------+-----------+

This will make the 245 field protected from change, unless the record source matches
d) go to /cgi-bin/koha/catalogue/detail.pl?biblionumber=262 and change 245 (title)  via edit -> edit record
e) save and take a look the title is still the same
f) run the updateBiblio-Request from below with a API-testing client like REST Client
g) check that title gets overwritten even though it is protected. This is due the fact the updateBiblio is not setting an overlay context.

h) apply patch
redo d) and e)
i) add another overlay rule allowing your record source to change 245:
+----+-----+--------+----------+-----------+
| id | tag | module | filter   | preset    |
+----+-----+--------+----------+-----------+
|  1 | 245 | source | *        | protect   |
|  2 | 245 | source | <NAME>   | overwrite |
+----+-----+--------+----------+-----------+

j) run the updateBiblio-Request from below, be sure to fill out x-record-source-id:with your ID from step b)
k) check that title gets overwritten
l) run the updateBiblio-Request from below, but omit x-record-source-id or set it to another value than <ID>
m) check that title is not overwritten

PUT http://main-intra.localhost/api/v1/biblios/262
Authorization: Basic koha:koha
Authorization: Basic koha:koha
Content-Type: application/marcxml+xml
x-record-source-id: <ID>

<?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>01075cam a2200313 a 4500</leader>
  <controlfield tag="001">foo</controlfield>
  <controlfield tag="005">20200421093825.0</controlfield>
  <controlfield tag="008">120417s2012    ch a     b    001 0 eng  </controlfield>
  <datafield tag="040" ind1=" " ind2=" ">
    <subfield code="c">482</subfield>
  </datafield>
  <datafield tag="100" ind1="1" ind2=" ">
    <subfield code="a">Christiansen, Tom.</subfield>
    <subfield code="9">482</subfield>
  </datafield>
  <datafield tag="245" ind1="1" ind2="0">
    <subfield code="a">New Title</subfield>
    <subfield code="c">Tom Christiansen, Brian D. Foy &amp; Larry Wall.</subfield>
  </datafield>
  <datafield tag="260" ind1=" " ind2=" ">
    <subfield code="a">City</subfield>
  </datafield>
  <datafield tag="300" ind1=" " ind2=" ">
    <subfield code="a">Pages and more</subfield>
  </datafield>
  <datafield tag="942" ind1=" " ind2=" ">
    <subfield code="c">BKS</subfield>
  </datafield>
</record>

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
This commit is contained in:
Jan Kissig 2026-03-13 10:18:29 +00:00 committed by Martin Renvoize
parent 246f299df1
commit ce42c3b5ec
No known key found for this signature in database
GPG Key ID: 2D86E0EAEC83711B
2 changed files with 58 additions and 2 deletions

View File

@ -22,6 +22,7 @@ use Mojo::Base 'Mojolicious::Controller';
use Koha::Biblios;
use Koha::DateUtils;
use Koha::Ratings;
use Koha::RecordSources;
use C4::Biblio qw( DelBiblio AddBiblio ModBiblio );
use C4::Search qw( FindDuplicate );
@ -720,9 +721,14 @@ sub update {
my $biblio = Koha::Biblios->find( $c->param('biblio_id') );
$c->render_resource_not_found("Bibliographic record")
return $c->render_resource_not_found("Bibliographic record")
unless $biblio;
return $c->render(
status => 403,
openapi => { error => 'You do not have permission to edit a locked record' }
) unless ( $biblio->can_be_edited( $c->stash('koha.user') ) );
try {
my $headers = $c->req->headers;
@ -753,7 +759,52 @@ sub update {
);
}
ModBiblio( $record, $biblio->id, $frameworkcode );
my $record_source_id = $headers->header('x-record-source-id');
my $options = {
overlay_context => {
userid => $c->stash('koha.user')->userid,
categorycode => $c->stash('koha.user')->categorycode,
}
};
if ($record_source_id) {
# We've been passed a record source. Verify they are allowed to
unless (
haspermission(
$c->stash('koha.user')->userid,
{ editcatalogue => 'set_record_sources' }
)
)
{
return $c->render(
status => 403,
openapi => { error => 'You do not have permission to set the record source' }
);
}
# find record source name to given id
my $record_source = Koha::RecordSources->search( { record_source_id => $record_source_id } )->single;
unless ($record_source) {
return $c->render(
status => 409,
openapi => { error => 'Given record_source_id does not exist' }
);
}
$options->{'overlay_context'}->{'source'} = $record_source->name;
# this will update the record source id in biblio metadata
$options->{'record_source_id'} = $record_source_id;
}
unless ( $options->{'overlay_context'}->{'source'} ) {
$options->{'overlay_context'}->{source} = '*';
}
ModBiblio( $record, $biblio->id, $frameworkcode, $options );
$c->render(
status => 200,

View File

@ -251,6 +251,7 @@
- $ref: "../swagger.yaml#/parameters/framework_id_header"
- $ref: "../swagger.yaml#/parameters/marc_schema_header"
- $ref: "../swagger.yaml#/parameters/confirm_not_duplicate_header"
- $ref: "../swagger.yaml#/parameters/record_source_id_header"
produces:
- application/json
responses:
@ -279,6 +280,10 @@
description: Accepted content-types
items:
type: string
"409":
description: Conflict
schema:
$ref: "../swagger.yaml#/definitions/error"
"500":
description: |
Internal server error. Possible `error_code` attribute values: