View | Details | Raw Unified | Return to bug 35104
Collapse All | Expand All

(-)a/Koha/REST/V1/Biblios/MetadataErrors.pm (+58 lines)
Line 0 Link Here
1
package Koha::REST::V1::Biblios::MetadataErrors;
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <https://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
20
use Mojo::Base 'Mojolicious::Controller';
21
22
use Koha::Biblio::Metadata::Errors;
23
use Koha::Biblios;
24
25
use Try::Tiny;
26
27
=head1 NAME
28
29
Koha::REST::V1::Biblios::MetadataErrors - REST controller for biblio metadata errors
30
31
=head1 API
32
33
=head2 Methods
34
35
=head3 delete
36
37
Delete (resolve) a single biblio metadata error row.
38
39
=cut
40
41
sub delete {
42
    my $c = shift->openapi->valid_input or return;
43
44
    my $biblio = Koha::Biblios->find( $c->param('biblio_id') );
45
    return $c->render_resource_not_found("Biblio") unless $biblio;
46
47
    my $error = $biblio->metadata->metadata_errors->find( $c->param('error_id') );
48
    return $c->render_resource_not_found("Metadata error") unless $error;
49
50
    return try {
51
        $error->delete;
52
        return $c->render_resource_deleted;
53
    } catch {
54
        $c->unhandled_exception($_);
55
    };
56
}
57
58
1;
(-)a/api/v1/swagger/paths/biblios_metadata_errors.yaml (+48 lines)
Line 0 Link Here
1
---
2
"/biblios/{biblio_id}/metadata/errors/{error_id}":
3
  delete:
4
    x-mojo-to: Biblios::MetadataErrors#delete
5
    operationId: deleteBiblioMetadataError
6
    tags:
7
    - biblios
8
    summary: Delete a biblio metadata error
9
    description: Deletes a specific metadata error record, marking it as resolved.
10
    parameters:
11
    - name: biblio_id
12
      in: path
13
      description: Internal identifier for the bibliographic record
14
      required: true
15
      type: integer
16
    - name: error_id
17
      in: path
18
      description: Internal identifier for the metadata error
19
      required: true
20
      type: integer
21
    produces:
22
    - application/json
23
    responses:
24
      '204':
25
        description: Metadata error deleted
26
      '401':
27
        description: Authentication required
28
        schema:
29
          "$ref": "../swagger.yaml#/definitions/error"
30
      '403':
31
        description: Access forbidden
32
        schema:
33
          "$ref": "../swagger.yaml#/definitions/error"
34
      '404':
35
        description: Metadata error not found
36
        schema:
37
          "$ref": "../swagger.yaml#/definitions/error"
38
      '500':
39
        description: Internal error
40
        schema:
41
          "$ref": "../swagger.yaml#/definitions/error"
42
      '503':
43
        description: Under maintenance
44
        schema:
45
          "$ref": "../swagger.yaml#/definitions/error"
46
    x-koha-authorization:
47
      permissions:
48
        editcatalogue: edit_catalogue
(-)a/api/v1/swagger/swagger.yaml (+2 lines)
Lines 299-304 paths: Link Here
299
    $ref: "./paths/biblios_item_groups.yaml#/~1biblios~1{biblio_id}~1item_groups~1{item_group_id}~1items"
299
    $ref: "./paths/biblios_item_groups.yaml#/~1biblios~1{biblio_id}~1item_groups~1{item_group_id}~1items"
300
  "/biblios/{biblio_id}/item_groups/{item_group_id}/items/{item_id}":
300
  "/biblios/{biblio_id}/item_groups/{item_group_id}/items/{item_id}":
301
    $ref: "./paths/biblios_item_groups.yaml#/~1biblios~1{biblio_id}~1item_groups~1{item_group_id}~1items~1{item_id}"
301
    $ref: "./paths/biblios_item_groups.yaml#/~1biblios~1{biblio_id}~1item_groups~1{item_group_id}~1items~1{item_id}"
302
  "/biblios/{biblio_id}/metadata/errors/{error_id}":
303
    $ref: "./paths/biblios_metadata_errors.yaml#/~1biblios~1{biblio_id}~1metadata~1errors~1{error_id}"
302
  "/biblios/{biblio_id}/merge":
304
  "/biblios/{biblio_id}/merge":
303
    $ref: "./paths/biblios_merge.yaml#/~1biblios~1{biblio_id}~1merge"
305
    $ref: "./paths/biblios_merge.yaml#/~1biblios~1{biblio_id}~1merge"
304
  /cash_registers:
306
  /cash_registers:
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/addbiblio.tt (-2 / +23 lines)
Lines 208-213 Link Here
208
                window.scrollTo(0, getScrollto($li.attr("id"), "toolbar"));
208
                window.scrollTo(0, getScrollto($li.attr("id"), "toolbar"));
209
            });
209
            });
210
210
211
            $("body").on("click", ".nonxml-resolve", function(e){
212
                e.preventDefault();
213
                var errorId  = $(this).data("error-id");
214
                var biblioId = $(this).data("biblio-id");
215
                var $item    = $("#nonxml-error-" + errorId);
216
                $.ajax({
217
                    url:    "/api/v1/biblios/" + biblioId + "/metadata/errors/" + errorId,
218
                    method: "DELETE",
219
                    success: function(){
220
                        $item.remove();
221
                        if ( $("#nonxml-error-list li").length === 0 ) {
222
                            $("#nonxml-errors-notice").remove();
223
                        }
224
                    },
225
                    error: function(){
226
                        alert( _("Failed to mark error as resolved. Please try again.") );
227
                    }
228
                });
229
            });
230
211
        });
231
        });
212
232
213
        function selectTab( tablink ){
233
        function selectTab( tablink ){
Lines 817-825 Link Here
817
        <div class="alert alert-warning" id="nonxml-errors-notice">
837
        <div class="alert alert-warning" id="nonxml-errors-notice">
818
            <h2>Data quality warnings</h2>
838
            <h2>Data quality warnings</h2>
819
            <p><strong>Non-XML characters were automatically stripped from this record when it was last saved. Please review the affected fields and correct or confirm the data.</strong></p>
839
            <p><strong>Non-XML characters were automatically stripped from this record when it was last saved. Please review the affected fields and correct or confirm the data.</strong></p>
820
            <ul>
840
            <ul id="nonxml-error-list">
821
                [% FOREACH err IN existing_nonxml_errors %]
841
                [% FOREACH err IN existing_nonxml_errors %]
822
                    <li>
842
                    <li id="nonxml-error-[% err.id | html %]">
823
                        [% IF err.tag %]
843
                        [% IF err.tag %]
824
                            <a class="nonxml-linkfield btn btn-link" href="#" data-tag="[% err.tag | html %]" [% IF err.subfield %]data-subfield="[% err.subfield | html %]"[% END %]>
844
                            <a class="nonxml-linkfield btn btn-link" href="#" data-tag="[% err.tag | html %]" [% IF err.subfield %]data-subfield="[% err.subfield | html %]"[% END %]>
825
                                <i class="fa fa-arrow-right" aria-hidden="true"></i>
845
                                <i class="fa fa-arrow-right" aria-hidden="true"></i>
Lines 827-832 Link Here
827
                            </a>
847
                            </a>
828
                        [% END %]
848
                        [% END %]
829
                        <code>[% err.message | html %]</code>
849
                        <code>[% err.message | html %]</code>
850
                        <button class="nonxml-resolve btn btn-default btn-xs" data-error-id="[% err.id | html %]" data-biblio-id="[% biblionumber | html %]"> Mark resolved </button>
830
                    </li>
851
                    </li>
831
                [% END %]
852
                [% END %]
832
            </ul>
853
            </ul>
(-)a/t/db_dependent/api/v1/biblios_metadata_errors.t (-1 / +123 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/env perl
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <https://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
20
use Test::More tests => 2;
21
use Test::NoWarnings;
22
use Test::Mojo;
23
24
use t::lib::Mocks;
25
use t::lib::TestBuilder;
26
27
use Koha::Biblio::Metadata::Error;
28
use Koha::Database;
29
30
my $schema  = Koha::Database->new->schema;
31
my $builder = t::lib::TestBuilder->new;
32
33
t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
34
35
my $t = Test::Mojo->new('Koha::REST::V1');
36
37
subtest 'delete() tests' => sub {
38
39
    plan tests => 13;
40
41
    $schema->storage->txn_begin;
42
43
    my $password = 'thePassword123';
44
45
    my $unauthorized_patron = $builder->build_object(
46
        {
47
            class => 'Koha::Patrons',
48
            value => { flags => 0 }
49
        }
50
    );
51
    $unauthorized_patron->set_password( { password => $password, skip_validation => 1 } );
52
    my $unauth_userid = $unauthorized_patron->userid;
53
54
    my $authorized_patron = $builder->build_object(
55
        {
56
            class => 'Koha::Patrons',
57
            value => { flags => 0 }
58
        }
59
    );
60
    $authorized_patron->set_password( { password => $password, skip_validation => 1 } );
61
    my $auth_userid = $authorized_patron->userid;
62
63
    $builder->build(
64
        {
65
            source => 'UserPermission',
66
            value  => {
67
                borrowernumber => $authorized_patron->borrowernumber,
68
                module_bit     => 9,
69
                code           => 'edit_catalogue',
70
            },
71
        }
72
    );
73
74
    my $biblio      = $builder->build_sample_biblio;
75
    my $metadata_id = $biblio->metadata->id;
76
77
    my $error = Koha::Biblio::Metadata::Error->new(
78
        {
79
            metadata_id => $metadata_id,
80
            error_type  => 'nonxml_stripped',
81
            message     => '245$a: invalid char value 31 (U+001F) at position 5',
82
        }
83
    )->store;
84
    my $error_id = $error->id;
85
86
    # Unauthenticated
87
    $t->delete_ok( "/api/v1/biblios/" . $biblio->biblionumber . "/metadata/errors/$error_id" )
88
        ->status_is( 401, 'Unauthenticated request returns 401' );
89
90
    # Unauthorized (no permission)
91
    $t->delete_ok(
92
        "//$unauth_userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/metadata/errors/$error_id" )
93
        ->status_is( 403, 'Missing permission returns 403' );
94
95
    # Biblio not found
96
    $t->delete_ok("//$auth_userid:$password@/api/v1/biblios/0/metadata/errors/$error_id")
97
        ->status_is( 404, 'Non-existent biblio returns 404' );
98
99
    # Error not found (wrong error_id for this biblio)
100
    my $other_biblio = $builder->build_sample_biblio;
101
    my $other_error  = Koha::Biblio::Metadata::Error->new(
102
        {
103
            metadata_id => $other_biblio->metadata->id,
104
            error_type  => 'nonxml_stripped',
105
            message     => '245$a: invalid char value 31 (U+001F) at position 5',
106
        }
107
    )->store;
108
109
    $t->delete_ok(
110
        "//$auth_userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/metadata/errors/" . $other_error->id )
111
        ->status_is( 404, 'Error belonging to a different biblio returns 404' );
112
113
    # Successful delete
114
    $t->delete_ok( "//$auth_userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/metadata/errors/$error_id" )
115
        ->status_is( 204, 'Authorized delete of existing error returns 204' )
116
        ->content_is( '', 'No response body on successful delete' );
117
118
    # Already deleted / not found
119
    $t->delete_ok( "//$auth_userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/metadata/errors/$error_id" )
120
        ->status_is( 404, 'Deleting an already-deleted error returns 404' );
121
122
    $schema->storage->txn_rollback;
123
};

Return to bug 35104