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

(-)a/Koha/REST/V1/RecordSources.pm (+143 lines)
Line 0 Link Here
1
package Koha::REST::V1::RecordSources;
2
3
# Copyright 2023 Theke Solutions
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use Mojo::Base 'Mojolicious::Controller';
23
24
use Koha::RecordSources;
25
26
use Try::Tiny qw( catch try );
27
28
=head1 API
29
30
=head2 Methods
31
32
=head3 list
33
34
=cut
35
36
sub list {
37
    my $c = shift->openapi->valid_input or return;
38
39
    return try {
40
        return $c->render(
41
            status  => 200,
42
            openapi => $c->objects->search( Koha::RecordSources->new )
43
        );
44
    } catch {
45
        $c->unhandled_exception($_);
46
    };
47
}
48
49
=head3 get
50
51
=cut
52
53
sub get {
54
    my $c = shift->openapi->valid_input or return;
55
56
    return try {
57
        my $source = $c->objects->find( Koha::RecordSources->new, $c->param('record_source_id') );
58
        unless ($source) {
59
            return $c->render(
60
                status  => 404,
61
                openapi => { error => "Object not found" }
62
            );
63
        }
64
65
        return $c->render( status => 200, openapi => $source );
66
    } catch {
67
        $c->unhandled_exception($_);
68
    };
69
}
70
71
=head3 add
72
73
=cut
74
75
sub add {
76
    my $c = shift->openapi->valid_input or return;
77
78
    return try {
79
        my $source = Koha::RecordSource->new_from_api( $c->req->json );
80
        $source->store;
81
        $c->res->headers->location( $c->req->url->to_string . '/' . $source->record_source_id );
82
        return $c->render(
83
            status  => 201,
84
            openapi => $c->objects->to_api($source)
85
        );
86
    } catch {
87
        $c->unhandled_exception($_);
88
    };
89
}
90
91
=head3 update
92
93
=cut
94
95
sub update {
96
    my $c = shift->openapi->valid_input or return;
97
98
    my $source = $c->objects->find_rs( Koha::RecordSources->new, $c->param('record_source_id') );
99
100
    unless ($source) {
101
        return $c->render(
102
            status  => 404,
103
            openapi => { error => "Object not found" }
104
        );
105
    }
106
107
    return try {
108
        $source->set_from_api( $c->req->json )->store;
109
        $source->discard_changes;
110
        return $c->render( status => 200, openapi => $c->objects->to_api($source) );
111
    } catch {
112
        $c->unhandled_exception($_);
113
    };
114
}
115
116
=head3 delete
117
118
=cut
119
120
sub delete {
121
    my $c = shift->openapi->valid_input or return;
122
123
    my $source = $c->objects->find_rs( Koha::RecordSources->new, $c->param('record_source_id') );
124
125
    unless ($source) {
126
        return $c->render(
127
            status  => 404,
128
            openapi => { error => "Object not found" }
129
        );
130
    }
131
132
    return try {
133
        $source->delete;
134
        return $c->render(
135
            status  => 204,
136
            openapi => q{}
137
        );
138
    } catch {
139
        $c->unhandled_exception($_);
140
    };
141
}
142
143
1;
(-)a/api/v1/swagger/definitions/record_source.yaml (+16 lines)
Line 0 Link Here
1
---
2
type: object
3
properties:
4
  record_source_id:
5
    type: integer
6
    description: Internally assigned record source identifier
7
    readOnly: true
8
  name:
9
    description: Record source name
10
    type: string
11
  can_be_edited:
12
    description: If records from this source can be edited
13
    type: boolean
14
additionalProperties: false
15
required:
16
  - name
(-)a/api/v1/swagger/paths/record_sources.yaml (+246 lines)
Line 0 Link Here
1
/record_sources:
2
  get:
3
    x-mojo-to: RecordSources#list
4
    operationId: listRecordSources
5
    summary: List record sources
6
    tags:
7
      - record_sources
8
    parameters:
9
      - $ref: "../swagger.yaml#/parameters/match"
10
      - $ref: "../swagger.yaml#/parameters/order_by"
11
      - $ref: "../swagger.yaml#/parameters/page"
12
      - $ref: "../swagger.yaml#/parameters/per_page"
13
      - $ref: "../swagger.yaml#/parameters/q_param"
14
      - $ref: "../swagger.yaml#/parameters/q_body"
15
      - $ref: "../swagger.yaml#/parameters/request_id_header"
16
    consumes:
17
      - application/json
18
    produces:
19
      - application/json
20
    responses:
21
      "200":
22
        description: A list of record sources
23
        schema:
24
          type: array
25
          items:
26
            $ref: "../swagger.yaml#/definitions/record_source"
27
      "400":
28
        description: Missing or wrong parameters
29
        schema:
30
          $ref: "../swagger.yaml#/definitions/error"
31
      "401":
32
        description: Authentication required
33
        schema:
34
          $ref: "../swagger.yaml#/definitions/error"
35
      "403":
36
        description: Not allowed
37
        schema:
38
          $ref: "../swagger.yaml#/definitions/error"
39
      "500":
40
        description: |
41
          Internal server error. Possible `error_code` attribute values:
42
43
          * `internal_server_error`
44
        schema:
45
          $ref: "../swagger.yaml#/definitions/error"
46
      "503":
47
        description: Under maintenance
48
        schema:
49
          $ref: "../swagger.yaml#/definitions/error"
50
    x-koha-authorization:
51
      permissions:
52
        parameters: manage_record_sources
53
  post:
54
    x-mojo-to: RecordSources#add
55
    operationId: addRecordSources
56
    summary: Add a record source
57
    tags:
58
      - record_sources
59
    parameters:
60
      - name: body
61
        in: body
62
        description: A JSON object containing informations about the new record source
63
        required: true
64
        schema:
65
          $ref: "../swagger.yaml#/definitions/record_source"
66
    consumes:
67
      - application/json
68
    produces:
69
      - application/json
70
    responses:
71
      "201":
72
        description: A record source
73
        schema:
74
          $ref: "../swagger.yaml#/definitions/record_source"
75
      "400":
76
        description: Missing or wrong parameters
77
        schema:
78
          $ref: "../swagger.yaml#/definitions/error"
79
      "401":
80
        description: Authentication required
81
        schema:
82
          $ref: "../swagger.yaml#/definitions/error"
83
      "403":
84
        description: Not allowed
85
        schema:
86
          $ref: "../swagger.yaml#/definitions/error"
87
      "500":
88
        description: |
89
          Internal server error. Possible `error_code` attribute values:
90
91
          * `internal_server_error`
92
        schema:
93
          $ref: "../swagger.yaml#/definitions/error"
94
      "503":
95
        description: Under maintenance
96
        schema:
97
          $ref: "../swagger.yaml#/definitions/error"
98
    x-koha-authorization:
99
      permissions:
100
        parameters: manage_record_sources
101
"/record_sources/{record_source_id}":
102
  get:
103
    x-mojo-to: RecordSources#get
104
    operationId: getRecordSources
105
    summary: Get a record source
106
    tags:
107
      - record_sources
108
    parameters:
109
      - $ref: "../swagger.yaml#/parameters/record_source_id_pp"
110
    consumes:
111
      - application/json
112
    produces:
113
      - application/json
114
    responses:
115
      "200":
116
        description: A record source
117
        schema:
118
          $ref: "../swagger.yaml#/definitions/record_source"
119
      "400":
120
        description: Missing or wrong parameters
121
        schema:
122
          $ref: "../swagger.yaml#/definitions/error"
123
      "401":
124
        description: Authentication required
125
        schema:
126
          $ref: "../swagger.yaml#/definitions/error"
127
      "403":
128
        description: Not allowed
129
        schema:
130
          $ref: "../swagger.yaml#/definitions/error"
131
      "404":
132
        description: Not found
133
        schema:
134
          $ref: "../swagger.yaml#/definitions/error"
135
      "500":
136
        description: |
137
          Internal server error. Possible `error_code` attribute values:
138
139
          * `internal_server_error`
140
        schema:
141
          $ref: "../swagger.yaml#/definitions/error"
142
      "503":
143
        description: Under maintenance
144
        schema:
145
          $ref: "../swagger.yaml#/definitions/error"
146
    x-koha-authorization:
147
      permissions:
148
        parameters: manage_record_sources
149
  put:
150
    x-mojo-to: RecordSources#update
151
    operationId: updateRecordSources
152
    summary: Update a record source
153
    tags:
154
      - record_sources
155
    parameters:
156
      - $ref: "../swagger.yaml#/parameters/record_source_id_pp"
157
      - name: body
158
        in: body
159
        description: A JSON object containing informations about the new record source
160
        required: true
161
        schema:
162
          $ref: "../swagger.yaml#/definitions/record_source"
163
    consumes:
164
      - application/json
165
    produces:
166
      - application/json
167
    responses:
168
      "200":
169
        description: A record source
170
        schema:
171
          $ref: "../swagger.yaml#/definitions/record_source"
172
      "400":
173
        description: Missing or wrong parameters
174
        schema:
175
          $ref: "../swagger.yaml#/definitions/error"
176
      "401":
177
        description: Authentication required
178
        schema:
179
          $ref: "../swagger.yaml#/definitions/error"
180
      "403":
181
        description: Not allowed
182
        schema:
183
          $ref: "../swagger.yaml#/definitions/error"
184
      "404":
185
        description: Not found
186
        schema:
187
          $ref: "../swagger.yaml#/definitions/error"
188
      "500":
189
        description: |
190
          Internal server error. Possible `error_code` attribute values:
191
192
          * `internal_server_error`
193
        schema:
194
          $ref: "../swagger.yaml#/definitions/error"
195
      "503":
196
        description: Under maintenance
197
        schema:
198
          $ref: "../swagger.yaml#/definitions/error"
199
    x-koha-authorization:
200
      permissions:
201
        parameters: manage_record_sources
202
  delete:
203
    x-mojo-to: RecordSources#delete
204
    operationId: deleteRecordSources
205
    summary: Delete a record source
206
    tags:
207
      - record_sources
208
    parameters:
209
      - $ref: "../swagger.yaml#/parameters/record_source_id_pp"
210
    consumes:
211
      - application/json
212
    produces:
213
      - application/json
214
    responses:
215
      "204":
216
        description: Deleted
217
      "400":
218
        description: Missing or wrong parameters
219
        schema:
220
          $ref: "../swagger.yaml#/definitions/error"
221
      "401":
222
        description: Authentication required
223
        schema:
224
          $ref: "../swagger.yaml#/definitions/error"
225
      "403":
226
        description: Not allowed
227
        schema:
228
          $ref: "../swagger.yaml#/definitions/error"
229
      "404":
230
        description: Not found
231
        schema:
232
          $ref: "../swagger.yaml#/definitions/error"
233
      "500":
234
        description: |
235
          Internal server error. Possible `error_code` attribute values:
236
237
          * `internal_server_error`
238
        schema:
239
          $ref: "../swagger.yaml#/definitions/error"
240
      "503":
241
        description: Under maintenance
242
        schema:
243
          $ref: "../swagger.yaml#/definitions/error"
244
    x-koha-authorization:
245
      permissions:
246
        parameters: manage_record_sources
(-)a/api/v1/swagger/swagger.yaml (+15 lines)
Lines 108-113 definitions: Link Here
108
    $ref: ./definitions/import_batch_profiles.yaml
108
    $ref: ./definitions/import_batch_profiles.yaml
109
  import_record_match:
109
  import_record_match:
110
    $ref: ./definitions/import_record_match.yaml
110
    $ref: ./definitions/import_record_match.yaml
111
  record_source:
112
    $ref: ./definitions/record_source.yaml
111
  invoice:
113
  invoice:
112
    $ref: ./definitions/invoice.yaml
114
    $ref: ./definitions/invoice.yaml
113
  item:
115
  item:
Lines 487-492 paths: Link Here
487
    $ref: ./paths/quotes.yaml#/~1quotes
489
    $ref: ./paths/quotes.yaml#/~1quotes
488
  "/quotes/{quote_id}":
490
  "/quotes/{quote_id}":
489
    $ref: "./paths/quotes.yaml#/~1quotes~1{quote_id}"
491
    $ref: "./paths/quotes.yaml#/~1quotes~1{quote_id}"
492
  /record_sources:
493
    $ref: ./paths/record_sources.yaml#/~1record_sources
494
  "/record_sources/{record_source_id}":
495
    $ref: ./paths/record_sources.yaml#/~1record_sources~1{record_source_id}
490
  /return_claims:
496
  /return_claims:
491
    $ref: ./paths/return_claims.yaml#/~1return_claims
497
    $ref: ./paths/return_claims.yaml#/~1return_claims
492
  "/return_claims/{claim_id}":
498
  "/return_claims/{claim_id}":
Lines 717-722 parameters: Link Here
717
    name: import_record_id
723
    name: import_record_id
718
    required: true
724
    required: true
719
    type: integer
725
    type: integer
726
  record_source_id_pp:
727
    description: Internal record source identifier
728
    in: path
729
    name: record_source_id
730
    required: true
731
    type: integer
720
  item_id_pp:
732
  item_id_pp:
721
    description: Internal item identifier
733
    description: Internal item identifier
722
    in: path
734
    in: path
Lines 1120-1125 tags: Link Here
1120
  - description: "Manage item groups\n"
1132
  - description: "Manage item groups\n"
1121
    name: item_groups
1133
    name: item_groups
1122
    x-displayName: Item groups
1134
    x-displayName: Item groups
1135
  - description: "Manage record sources\n"
1136
    name: record_sources
1137
    x-displayName: Record source
1123
  - description: "Manage items\n"
1138
  - description: "Manage items\n"
1124
    name: items
1139
    name: items
1125
    x-displayName: Items
1140
    x-displayName: Items
(-)a/t/db_dependent/api/v1/record_sources.t (-1 / +301 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/env perl
2
3
# Copyright 2023 Theke Solutions
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use Test::More tests => 5;
23
use Test::Mojo;
24
25
use t::lib::TestBuilder;
26
use t::lib::Mocks;
27
28
use Koha::RecordSources;
29
use Koha::Database;
30
31
my $schema  = Koha::Database->new->schema;
32
my $builder = t::lib::TestBuilder->new;
33
34
t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
35
36
my $t = Test::Mojo->new('Koha::REST::V1');
37
38
subtest 'list() tests' => sub {
39
40
    plan tests => 12;
41
42
    $schema->storage->txn_begin;
43
44
    my $source = $builder->build_object( { class => 'Koha::RecordSources' } );
45
    my $patron = $builder->build_object(
46
        {
47
            class => 'Koha::Patrons',
48
            value => { flags => 3 }
49
        }
50
    );
51
52
    for ( 1 .. 10 ) {
53
        $builder->build_object( { class => 'Koha::RecordSources' } );
54
    }
55
56
    my $nonprivilegedpatron = $builder->build_object(
57
        {
58
            class => 'Koha::Patrons',
59
            value => { flags => 0 }
60
        }
61
    );
62
63
    my $password = 'thePassword123';
64
65
    $nonprivilegedpatron->set_password( { password => $password, skip_validation => 1 } );
66
    my $userid = $nonprivilegedpatron->userid;
67
68
    $t->get_ok("//$userid:$password@/api/v1/record_sources")->status_is(403)
69
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
70
71
    $patron->set_password( { password => $password, skip_validation => 1 } );
72
    $userid = $patron->userid;
73
74
    $t->get_ok("//$userid:$password@/api/v1/record_sources?_per_page=10")->status_is( 200, 'SWAGGER3.2.2' );
75
76
    my $response_count = scalar @{ $t->tx->res->json };
77
78
    is( $response_count, 10, 'The API returns 10 sources' );
79
80
    my $id = $source->record_source_id;
81
    $t->get_ok("//$userid:$password@/api/v1/record_sources?q={\"record_source_id\": $id}")->status_is(200)
82
        ->json_is( '' => [ $source->to_api ], 'SWAGGER3.3.2' );
83
84
    $source->delete;
85
86
    $t->get_ok("//$userid:$password@/api/v1/record_sources?q={\"record_source_id\": $id}")->status_is(200)
87
        ->json_is( '' => [] );
88
89
    $schema->storage->txn_rollback;
90
};
91
92
subtest 'get() tests' => sub {
93
94
    plan tests => 9;
95
96
    $schema->storage->txn_begin;
97
98
    my $source = $builder->build_object( { class => 'Koha::RecordSources' } );
99
    my $patron = $builder->build_object(
100
        {
101
            class => 'Koha::Patrons',
102
            value => { flags => 3 }
103
        }
104
    );
105
106
    my $nonprivilegedpatron = $builder->build_object(
107
        {
108
            class => 'Koha::Patrons',
109
            value => { flags => 0 }
110
        }
111
    );
112
113
    my $password = 'thePassword123';
114
115
    $nonprivilegedpatron->set_password( { password => $password, skip_validation => 1 } );
116
    my $userid = $nonprivilegedpatron->userid;
117
118
    my $id = $source->record_source_id;
119
120
    $t->get_ok("//$userid:$password@/api/v1/record_sources/$id")->status_is(403)
121
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
122
123
    $patron->set_password( { password => $password, skip_validation => 1 } );
124
    $userid = $patron->userid;
125
126
    $t->get_ok("//$userid:$password@/api/v1/record_sources/$id")->status_is( 200, 'SWAGGER3.2.2' )
127
        ->json_is( '' => $source->to_api, 'SWAGGER3.3.2' );
128
129
    $source->delete;
130
131
    $t->get_ok("//$userid:$password@/api/v1/record_sources/$id")->status_is(404)
132
        ->json_is( '/error' => 'Object not found' );
133
134
    $schema->storage->txn_rollback;
135
};
136
137
subtest 'delete() tests' => sub {
138
139
    plan tests => 6;
140
141
    $schema->storage->txn_begin;
142
143
    my $source = $builder->build_object( { class => 'Koha::RecordSources' } );
144
    my $patron = $builder->build_object(
145
        {
146
            class => 'Koha::Patrons',
147
            value => { flags => 3 }
148
        }
149
    );
150
151
    my $nonprivilegedpatron = $builder->build_object(
152
        {
153
            class => 'Koha::Patrons',
154
            value => { flags => 0 }
155
        }
156
    );
157
158
    my $password = 'thePassword123';
159
160
    $nonprivilegedpatron->set_password( { password => $password, skip_validation => 1 } );
161
    my $userid = $nonprivilegedpatron->userid;
162
163
    my $id = $source->record_source_id;
164
165
    $t->delete_ok("//$userid:$password@/api/v1/record_sources/$id")->status_is(403)
166
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
167
168
    $patron->set_password( { password => $password, skip_validation => 1 } );
169
    $userid = $patron->userid;
170
171
    $t->delete_ok("//$userid:$password@/api/v1/record_sources/$id")->status_is( 204, 'SWAGGER3.2.2' );
172
173
    my $deleted_source = Koha::RecordSources->search( { record_source_id => $id } );
174
175
    is( $deleted_source->count, 0, 'No record source found' );
176
177
    $schema->storage->txn_rollback;
178
};
179
180
subtest 'add() tests' => sub {
181
182
    plan tests => 8;
183
184
    $schema->storage->txn_begin;
185
186
    my $patron = $builder->build_object(
187
        {
188
            class => 'Koha::Patrons',
189
            value => { flags => 3 }
190
        }
191
    );
192
193
    my $nonprivilegedpatron = $builder->build_object(
194
        {
195
            class => 'Koha::Patrons',
196
            value => { flags => 0 }
197
        }
198
    );
199
200
    my $password = 'thePassword123';
201
202
    $nonprivilegedpatron->set_password( { password => $password, skip_validation => 1 } );
203
    my $userid    = $nonprivilegedpatron->userid;
204
    my $patron_id = $nonprivilegedpatron->borrowernumber;
205
206
    $t->post_ok( "//$userid:$password@/api/v1/record_sources" => json => { name => 'test1' } )->status_is(403)
207
        ->json_is( '/error' => 'Authorization failure. Missing required permission(s).' );
208
209
    $patron->set_password( { password => $password, skip_validation => 1 } );
210
    $userid = $patron->userid;
211
212
    my $source_id =
213
        $t->post_ok( "//$userid:$password@/api/v1/record_sources" => json => { name => 'test1' } )
214
        ->status_is( 201, 'SWAGGER3.2.2' )->json_is( '/name', 'test1' )->json_is( '/can_be_edited', 0 )
215
        ->tx->res->json->{record_source_id};
216
217
    my $created_source = Koha::RecordSources->find($source_id);
218
219
    is( $created_source->name, 'test1', 'Record source found' );
220
221
    $schema->storage->txn_rollback;
222
};
223
224
subtest 'update() tests' => sub {
225
226
    plan tests => 15;
227
228
    $schema->storage->txn_begin;
229
230
    my $librarian = $builder->build_object(
231
        {
232
            class => 'Koha::Patrons',
233
            value => { flags => 2**3 }    # parameters flag = 2
234
        }
235
    );
236
    my $password = 'thePassword123';
237
    $librarian->set_password( { password => $password, skip_validation => 1 } );
238
    my $userid = $librarian->userid;
239
240
    my $patron = $builder->build_object(
241
        {
242
            class => 'Koha::Patrons',
243
            value => { flags => 0 }
244
        }
245
    );
246
247
    $patron->set_password( { password => $password, skip_validation => 1 } );
248
    my $unauth_userid = $patron->userid;
249
250
    my $source    = Koha::RecordSource->new( { name => 'old_name' } )->store;
251
    my $source_id = $source->id;
252
253
    # Unauthorized attempt to update
254
    $t->put_ok( "//$unauth_userid:$password@/api/v1/record_sources/$source_id" => json =>
255
            { name => 'New unauthorized name change' } )->status_is(403);
256
257
    # Attempt partial update on a PUT
258
    my $source_with_missing_field = {};
259
260
    $t->put_ok( "//$userid:$password@/api/v1/record_sources/$source_id" => json => $source_with_missing_field )
261
        ->status_is(400)->json_is( "/errors" => [ { message => "Missing property.", path => "/body/name" } ] );
262
263
    # Full object update on PUT
264
    my $source_with_updated_field = {
265
        name => "new_name",
266
    };
267
268
    $t->put_ok( "//$userid:$password@/api/v1/record_sources/$source_id" => json => $source_with_updated_field )
269
        ->status_is(200)->json_is( '/name' => $source_with_updated_field->{name} );
270
271
    # Authorized attempt to write invalid data
272
    my $source_with_invalid_field = {
273
        name   => "blah",
274
        potato => "yeah",
275
    };
276
277
    $t->put_ok( "//$userid:$password@/api/v1/record_sources/$source_id" => json => $source_with_invalid_field )
278
        ->status_is(400)->json_is(
279
        "/errors" => [
280
            {
281
                message => "Properties not allowed: potato.",
282
                path    => "/body"
283
            }
284
        ]
285
        );
286
287
    my $source_to_delete = $builder->build_object( { class => 'Koha::RecordSources' } );
288
    my $non_existent_id  = $source_to_delete->id;
289
    $source_to_delete->delete;
290
291
    $t->put_ok( "//$userid:$password@/api/v1/record_sources/$non_existent_id" => json => $source_with_updated_field )
292
        ->status_is(404);
293
294
    # Wrong method (POST)
295
    $source_with_updated_field->{record_source_id} = 2;
296
297
    $t->post_ok( "//$userid:$password@/api/v1/record_sources/$source_id" => json => $source_with_updated_field )
298
        ->status_is(404);
299
300
    $schema->storage->txn_rollback;
301
};

Return to bug 35919