Bug 17387: (follow-up) move records_restore under editcatalogue permission

The restore functionality is a cataloguing operation and should live
under the editcatalogue permission module (bit 9) rather than tools
(bit 13), consistent with where it appears in the UI.

Update all references:
- userpermissions.sql and atomicupdate: module_bit 13 → 9
- Swagger x-koha-authorization: tools → editcatalogue
- CGI flagsrequired: tools → editcatalogue
- Templates: CAN_user_tools_records_restore → CAN_user_editcatalogue_records_restore
- C4::Auth::get_cataloguing_page_permissions: remove from tools
  sub-perms list (editcatalogue '*' already covers it)
- Tests: module_bit 13 → 9

Signed-off-by: Michaela <michaela.sieber@kit.edu>
Sponsored-by: ByWater Solutions
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This commit is contained in:
Martin Renvoize 2026-03-01 16:58:37 +00:00 committed by Lucas Gass
parent 06f4abbf9a
commit 8681b48fdb
No known key found for this signature in database
GPG Key ID: 60B447398B0D36CA
10 changed files with 28 additions and 21 deletions

View File

@ -2329,7 +2329,6 @@ sub get_cataloguing_page_permissions {
marc_modification_templates marc_modification_templates
records_batchdel records_batchdel
records_batchmod records_batchmod
records_restore
stage_marc_import stage_marc_import
upload_cover_images upload_cover_images
); );

View File

@ -206,4 +206,4 @@
$ref: "../swagger.yaml#/definitions/error" $ref: "../swagger.yaml#/definitions/error"
x-koha-authorization: x-koha-authorization:
permissions: permissions:
tools: records_restore editcatalogue: records_restore

View File

@ -164,4 +164,4 @@
$ref: "../swagger.yaml#/definitions/error" $ref: "../swagger.yaml#/definitions/error"
x-koha-authorization: x-koha-authorization:
permissions: permissions:
tools: records_restore editcatalogue: records_restore

View File

@ -11,11 +11,11 @@ return {
$dbh->do( $dbh->do(
q{ q{
INSERT IGNORE INTO permissions (module_bit, code, description) INSERT IGNORE INTO permissions (module_bit, code, description)
VALUES (13, 'records_restore', 'Restore deleted records') VALUES (9, 'records_restore', 'Restore deleted bibliographic records and items')
} }
); );
say_success( $out, "Added new permission 'tools:records_restore'" ); say_success( $out, "Added new permission 'editcatalogue:records_restore'" );
}, },
}; };

View File

@ -71,6 +71,7 @@ INSERT INTO permissions (module_bit, code, description) VALUES
( 9, 'edit_any_item', 'Edit any item regardless of home library'), ( 9, 'edit_any_item', 'Edit any item regardless of home library'),
( 9, 'edit_locked_records', 'Edit locked records'), ( 9, 'edit_locked_records', 'Edit locked records'),
( 9, 'set_record_sources', 'Set record source'), ( 9, 'set_record_sources', 'Set record source'),
( 9, 'records_restore', 'Restore deleted bibliographic records and items'),
(10, 'payout', 'Perform account payout action'), (10, 'payout', 'Perform account payout action'),
(10, 'refund', 'Perform account refund action'), (10, 'refund', 'Perform account refund action'),
(10, 'discount', 'Perform account discount action'), (10, 'discount', 'Perform account discount action'),
@ -133,7 +134,6 @@ INSERT INTO permissions (module_bit, code, description) VALUES
(13, 'records_batchmod', 'Perform batch modification of records (biblios or authorities)'), (13, 'records_batchmod', 'Perform batch modification of records (biblios or authorities)'),
(13, 'marc_modification_templates', 'Manage marc modification templates'), (13, 'marc_modification_templates', 'Manage marc modification templates'),
(13, 'records_batchdel', 'Perform batch deletion of records (bibliographic or authority)'), (13, 'records_batchdel', 'Perform batch deletion of records (bibliographic or authority)'),
(13, 'records_restore', 'Restore deleted bibliographic records and items'),
(13, 'access_files', 'Access to the files stored on the server'), (13, 'access_files', 'Access to the files stored on the server'),
(13, 'upload_general_files', 'Upload any file'), (13, 'upload_general_files', 'Upload any file'),
(13, 'upload_manage', 'Manage uploaded files'), (13, 'upload_manage', 'Manage uploaded files'),

View File

@ -43,7 +43,7 @@
</ul> </ul>
[% END %] [% END %]
[% IF ( CAN_user_tools_items_batchmod || CAN_user_tools_items_batchdel || CAN_user_tools_records_batchmod || CAN_user_tools_records_batchdel || CAN_user_tools_records_restore || CAN_user_tools_marc_modification_templates ) %] [% IF ( CAN_user_tools_items_batchmod || CAN_user_tools_items_batchdel || CAN_user_tools_records_batchmod || CAN_user_tools_records_batchdel || CAN_user_editcatalogue_records_restore || CAN_user_tools_marc_modification_templates ) %]
<h5>Batch editing</h5> <h5>Batch editing</h5>
<ul> <ul>
[% IF ( CAN_user_tools_items_batchmod ) %] [% IF ( CAN_user_tools_items_batchmod ) %]
@ -71,7 +71,7 @@
<a href="/cgi-bin/koha/tools/marc_modification_templates.pl">MARC modification templates</a> <a href="/cgi-bin/koha/tools/marc_modification_templates.pl">MARC modification templates</a>
</li> </li>
[% END %] [% END %]
[% IF ( CAN_user_tools_records_restore ) %] [% IF ( CAN_user_editcatalogue_records_restore ) %]
<li> <li>
<a href="/cgi-bin/koha/tools/restore-records.pl">Restore deleted records</a> <a href="/cgi-bin/koha/tools/restore-records.pl">Restore deleted records</a>
</li> </li>

View File

@ -120,7 +120,7 @@
</div> </div>
<div class="col-sm-4 col-md-4"> <div class="col-sm-4 col-md-4">
[% IF ( CAN_user_tools_items_batchmod || CAN_user_tools_items_batchdel || CAN_user_tools_records_batchmod || CAN_user_tools_records_batchdel || CAN_user_tools_records_restore || CAN_user_tools_marc_modification_templates ) %] [% IF ( CAN_user_tools_items_batchmod || CAN_user_tools_items_batchdel || CAN_user_tools_records_batchmod || CAN_user_tools_records_batchdel || CAN_user_editcatalogue_records_restore || CAN_user_tools_marc_modification_templates ) %]
<h3>Batch editing</h3> <h3>Batch editing</h3>
<ul class="buttons-list"> <ul class="buttons-list">
[% IF ( CAN_user_tools_items_batchmod ) %] [% IF ( CAN_user_tools_items_batchmod ) %]
@ -149,7 +149,7 @@
<a class="circ-button" href="/cgi-bin/koha/tools/marc_modification_templates.pl"><i class="fa fa-gear"></i> MARC modification templates</a> <a class="circ-button" href="/cgi-bin/koha/tools/marc_modification_templates.pl"><i class="fa fa-gear"></i> MARC modification templates</a>
</li> </li>
[% END %] [% END %]
[% IF ( CAN_user_tools_records_restore ) %] [% IF ( CAN_user_editcatalogue_records_restore ) %]
<li> <li>
<a class="circ-button" href="/cgi-bin/koha/tools/restore-records.pl"><i class="fa fa-undo"></i> Restore deleted records</a> <a class="circ-button" href="/cgi-bin/koha/tools/restore-records.pl"><i class="fa fa-undo"></i> Restore deleted records</a>
</li> </li>

View File

@ -293,7 +293,7 @@ subtest 'restore() tests' => sub {
source => 'UserPermission', source => 'UserPermission',
value => { value => {
borrowernumber => $librarian->borrowernumber, borrowernumber => $librarian->borrowernumber,
module_bit => 13, module_bit => 9,
code => 'records_restore', code => 'records_restore',
} }
} }
@ -326,7 +326,8 @@ subtest 'restore() tests' => sub {
$t->put_ok("//$unauth_userid:$password@/api/v1/deleted/biblios/$biblionumber")->status_is(403); $t->put_ok("//$unauth_userid:$password@/api/v1/deleted/biblios/$biblionumber")->status_is(403);
$t->put_ok("//$userid:$password@/api/v1/deleted/biblios/$biblionumber")->status_is(200) $t->put_ok("//$userid:$password@/api/v1/deleted/biblios/$biblionumber")
->status_is(200)
->json_is( '/biblio_id' => $biblionumber ); ->json_is( '/biblio_id' => $biblionumber );
my $restored_biblio = Koha::Biblios->find($biblionumber); my $restored_biblio = Koha::Biblios->find($biblionumber);
@ -362,7 +363,7 @@ subtest 'restore() with library group permissions tests' => sub {
source => 'UserPermission', source => 'UserPermission',
value => { value => {
borrowernumber => $librarian->borrowernumber, borrowernumber => $librarian->borrowernumber,
module_bit => 13, module_bit => 9,
code => 'records_restore', code => 'records_restore',
} }
} }
@ -413,8 +414,11 @@ subtest 'restore() with library group permissions tests' => sub {
$t->put_ok( $t->put_ok(
"//$userid:$password@/api/v1/deleted/biblios/$biblionumber" => { 'Content-Type' => 'application/json' } => "//$userid:$password@/api/v1/deleted/biblios/$biblionumber" => { 'Content-Type' => 'application/json' } =>
$body )->status_is(200)->json_is( '/biblio_id' => $biblionumber ) $body )
->json_is( '/restored_items/0' => $item1_id )->json_is( '/skipped_items/0' => $item2_id ); ->status_is(200)
->json_is( '/biblio_id' => $biblionumber )
->json_is( '/restored_items/0' => $item1_id )
->json_is( '/skipped_items/0' => $item2_id );
my $restored_biblio = Koha::Biblios->find($biblionumber); my $restored_biblio = Koha::Biblios->find($biblionumber);
ok( $restored_biblio, 'Biblio restored' ); ok( $restored_biblio, 'Biblio restored' );

View File

@ -120,7 +120,8 @@ subtest 'get() tests' => sub {
my $non_existent_id = $item_id + 99999; my $non_existent_id = $item_id + 99999;
$t->get_ok("//$userid:$password@/api/v1/deleted/items/$non_existent_id")->status_is(404) $t->get_ok("//$userid:$password@/api/v1/deleted/items/$non_existent_id")
->status_is(404)
->json_is( '/error' => 'Item not found' ); ->json_is( '/error' => 'Item not found' );
$schema->storage->txn_rollback; $schema->storage->txn_rollback;
@ -147,7 +148,7 @@ subtest 'restore() tests' => sub {
source => 'UserPermission', source => 'UserPermission',
value => { value => {
borrowernumber => $librarian->borrowernumber, borrowernumber => $librarian->borrowernumber,
module_bit => 13, module_bit => 9,
code => 'records_restore', code => 'records_restore',
} }
} }
@ -196,7 +197,9 @@ subtest 'restore() tests' => sub {
$item_without_biblio->delete; $item_without_biblio->delete;
Koha::Biblios->find($orphan_biblio_id)->delete; Koha::Biblios->find($orphan_biblio_id)->delete;
$t->put_ok("//$userid:$password@/api/v1/deleted/items/$orphan_item_id")->status_is(409)->json_has('/error') $t->put_ok("//$userid:$password@/api/v1/deleted/items/$orphan_item_id")
->status_is(409)
->json_has('/error')
->json_like( '/error', qr/Bibliographic record not found/ ); ->json_like( '/error', qr/Bibliographic record not found/ );
$schema->storage->txn_rollback; $schema->storage->txn_rollback;
@ -223,7 +226,7 @@ subtest 'restore() with library group permissions tests' => sub {
source => 'UserPermission', source => 'UserPermission',
value => { value => {
borrowernumber => $librarian->borrowernumber, borrowernumber => $librarian->borrowernumber,
module_bit => 13, module_bit => 9,
code => 'records_restore', code => 'records_restore',
} }
} }
@ -262,7 +265,8 @@ subtest 'restore() with library group permissions tests' => sub {
my $restored_item = Koha::Items->find($item_allowed_id); my $restored_item = Koha::Items->find($item_allowed_id);
ok( $restored_item, 'Item from allowed library restored' ); ok( $restored_item, 'Item from allowed library restored' );
$t->put_ok("//$userid:$password@/api/v1/deleted/items/$item_restricted_id")->status_is(403) $t->put_ok("//$userid:$password@/api/v1/deleted/items/$item_restricted_id")
->status_is(403)
->json_is( '/error' => 'You do not have permission to restore items from this library.' ); ->json_is( '/error' => 'You do not have permission to restore items from this library.' );
my $not_restored = Koha::Items->find($item_restricted_id); my $not_restored = Koha::Items->find($item_restricted_id);

View File

@ -31,7 +31,7 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
template_name => "tools/restore-records.tt", template_name => "tools/restore-records.tt",
query => $input, query => $input,
type => "intranet", type => "intranet",
flagsrequired => { tools => 'records_restore' }, flagsrequired => { editcatalogue => 'records_restore' },
} }
); );