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

(-)a/Koha/REST/V1/AuthorisedValues.pm (+109 lines)
Lines 20-25 use Modern::Perl; Link Here
20
use Mojo::Base 'Mojolicious::Controller';
20
use Mojo::Base 'Mojolicious::Controller';
21
21
22
use Koha::AuthorisedValueCategories;
22
use Koha::AuthorisedValueCategories;
23
use Koha::AuthorisedValues;
23
24
24
use Try::Tiny;
25
use Try::Tiny;
25
26
Lines 52-58 sub list_av_from_category { Link Here
52
    } catch {
53
    } catch {
53
        $c->unhandled_exception($_);
54
        $c->unhandled_exception($_);
54
    };
55
    };
56
}
57
58
=head3 list
59
60
=cut
61
62
sub list {
63
    my $c = shift->openapi->valid_input or return;
64
65
    return try {
66
        my $av_set = Koha::AuthorisedValues->new;
67
        my $avs = $c->objects->search( $av_set );
68
        return $c->render( status => 200, openapi => $avs );
69
    }
70
    catch {
71
        $c->unhandled_exception($_);
72
    };
73
74
}
75
76
=head3 get
77
78
=cut
79
80
sub get {
81
    my $c = shift->openapi->valid_input or return;
82
83
    return try {
84
        my $av = Koha::AuthorisedValues->find( $c->validation->param('authorised_value_id') );
85
        unless ($av) {
86
            return $c->render( status  => 404,
87
                            openapi => { error => "Authorised value not found" } );
88
        }
89
90
        return $c->render( status => 200, openapi => $av->to_api );
91
    }
92
    catch {
93
        $c->unhandled_exception($_);
94
    }
95
}
96
97
=head3 add
98
99
=cut
100
101
sub add {
102
    my $c = shift->openapi->valid_input or return;
103
104
    return try {
105
        my $av = Koha::AuthorisedValue->new_from_api( $c->validation->param('body') );
106
        $av->store;
107
        $c->res->headers->location( $c->req->url->to_string . '/' . $av->id );
108
        return $c->render(
109
            status  => 201,
110
            openapi => $av->to_api
111
        );
112
    }
113
    catch {
114
        $c->unhandled_exception($_);
115
    };
116
}
117
118
=head3 update
119
120
=cut
55
121
122
sub update {
123
    my $c = shift->openapi->valid_input or return;
124
125
    my $av = Koha::AuthorisedValues->find( $c->validation->param('authorised_value_id') );
126
127
    if ( not defined $av ) {
128
        return $c->render( status  => 404,
129
                           openapi => { error => "Object not found" } );
130
    }
131
132
    return try {
133
        $av->set_from_api( $c->validation->param('body') );
134
        $av->store();
135
        return $c->render( status => 200, openapi => $av->to_api );
136
    }
137
    catch {
138
        $c->unhandled_exception($_);
139
    };
140
}
141
142
=head3 delete
143
144
=cut
145
146
sub delete {
147
    my $c = shift->openapi->valid_input or return;
148
149
    my $av = Koha::AuthorisedValues->find( $c->validation->param('authorised_value_id') );
150
    if ( not defined $av ) {
151
        return $c->render( status  => 404,
152
                           openapi => { error => "Object not found" } );
153
    }
154
155
    return try {
156
        $av->delete;
157
        return $c->render(
158
            status  => 204,
159
            openapi => q{}
160
        );
161
    }
162
    catch {
163
        $c->unhandled_exception($_);
164
    };
56
}
165
}
57
166
58
1;
167
1;
(-)a/api/v1/swagger/paths/authorised_values.yaml (-1 / +215 lines)
Lines 1-4 Link Here
1
---
1
---
2
/authorised_values:
3
  get:
4
    operationId: listAuthorisedValues
5
    parameters:
6
      - description: Search authorised values by category
7
        in: query
8
        name: category
9
        required: false
10
        type: string
11
      - description: Search authorised values by value
12
        in: query
13
        name: value
14
        required: false
15
        type: string
16
      - description: Search authorised values by description
17
        in: query
18
        name: description
19
        required: false
20
        type: string
21
      - description: Search authorised values by opac description
22
        in: query
23
        name: opac_description
24
        required: false
25
        type: string
26
      - description: Search authorised values by image url
27
        in: query
28
        name: image_url
29
        required: false
30
        type: string
31
      - $ref: ../parameters.json#/match
32
      - $ref: ../parameters.json#/order_by
33
      - $ref: ../parameters.json#/page
34
      - $ref: ../parameters.json#/per_page
35
      - $ref: ../parameters.json#/q_param
36
      - $ref: ../parameters.json#/q_body
37
      - $ref: ../parameters.json#/q_header
38
    produces:
39
      - application/json
40
    responses:
41
      200:
42
        description: A list of authorised values
43
        schema:
44
          items:
45
            $ref: ../definitions.json#/authorised_value
46
          type: array
47
      403:
48
        description: Access forbidden
49
        schema:
50
          $ref: ../definitions.json#/error
51
      500:
52
        description: Internal error
53
        schema:
54
          $ref: ../definitions.json#/error
55
      503:
56
        description: Under maintenance
57
        schema:
58
          $ref: ../definitions.json#/error
59
    tags:
60
      - authorised
61
      - values
62
    x-koha-authorization:
63
      permissions:
64
        catalogue: 1
65
    x-mojo-to: AuthorisedValues#list
66
  post:
67
    operationId: addAuthorisedValue
68
    parameters:
69
      - description: A JSON object containing informations about the new authorised value
70
        in: body
71
        name: body
72
        required: true
73
        schema:
74
          $ref: ../definitions.json#/authorised_value
75
    produces:
76
      - application/json
77
    responses:
78
      201:
79
        description: Authorised value added
80
        schema:
81
          $ref: ../definitions.json#/authorised_value
82
      401:
83
        description: Authentication required
84
        schema:
85
          $ref: ../definitions.json#/error
86
      403:
87
        description: Access forbidden
88
        schema:
89
          $ref: ../definitions.json#/error
90
      500:
91
        description: Internal error
92
        schema:
93
          $ref: ../definitions.json#/error
94
      503:
95
        description: Under maintenance
96
        schema:
97
          $ref: ../definitions.json#/error
98
    tags:
99
      - authorised
100
      - values
101
    x-koha-authorization:
102
      permissions:
103
        parameters: manage_auth_values
104
    x-mojo-to: AuthorisedValues#add
105
"/authorised_values/{authorised_value_id}":
106
  delete:
107
    operationId: deleteAuthorisedValue
108
    parameters:
109
      - $ref: ../parameters.json#/authorised_value_id_pp
110
    produces:
111
      - application/json
112
    responses:
113
      204:
114
        description: Authorised value deleted
115
      401:
116
        description: Authentication required
117
        schema:
118
          $ref: ../definitions.json#/error
119
      403:
120
        description: Access forbidden
121
        schema:
122
          $ref: ../definitions.json#/error
123
      404:
124
        description: Authorised value not found
125
        schema:
126
          $ref: ../definitions.json#/error
127
      500:
128
        description: Internal error
129
        schema:
130
          $ref: ../definitions.json#/error
131
      503:
132
        description: Under maintenance
133
        schema:
134
          $ref: ../definitions.json#/error
135
    tags:
136
      - authorised
137
      - values
138
    x-koha-authorization:
139
      permissions:
140
        parameters: manage_auth_values
141
    x-mojo-to: AuthorisedValues#delete
142
  get:
143
    operationId: getAuthorisedValue
144
    parameters:
145
      - $ref: ../parameters.json#/authorised_value_id_pp
146
    produces:
147
      - application/json
148
    responses:
149
      200:
150
        description: An authorised value
151
        schema:
152
          $ref: ../definitions.json#/authorised_value
153
      404:
154
        description: Authorised value not found
155
        schema:
156
          $ref: ../definitions.json#/error
157
      500:
158
        description: Internal error
159
        schema:
160
          $ref: ../definitions.json#/error
161
      503:
162
        description: Under maintenance
163
        schema:
164
          $ref: ../definitions.json#/error
165
    tags:
166
      - authorised
167
      - values
168
    x-koha-authorization:
169
      permissions:
170
        catalogue: 1
171
    x-mojo-to: AuthorisedValues#get
172
  put:
173
    operationId: updateAuthorisedValue
174
    parameters:
175
      - $ref: ../parameters.json#/authorised_value_id_pp
176
      - description: An authorised value object
177
        in: body
178
        name: body
179
        required: true
180
        schema:
181
          $ref: ../definitions.json#/authorised_value
182
    produces:
183
      - application/json
184
    responses:
185
      200:
186
        description: An authorised value
187
        schema:
188
          $ref: ../definitions.json#/authorised_value
189
      401:
190
        description: Authentication required
191
        schema:
192
          $ref: ../definitions.json#/error
193
      403:
194
        description: Access forbidden
195
        schema:
196
          $ref: ../definitions.json#/error
197
      404:
198
        description: Authorised value not found
199
        schema:
200
          $ref: ../definitions.json#/error
201
      500:
202
        description: Internal error
203
        schema:
204
          $ref: ../definitions.json#/error
205
      503:
206
        description: Under maintenance
207
        schema:
208
          $ref: ../definitions.json#/error
209
    tags:
210
      - authorised
211
      - value
212
    x-koha-authorization:
213
      permissions:
214
        parameters: manage_auth_values
215
    x-mojo-to: AuthorisedValues#update
2
"/authorised_value_categories/{authorised_value_category_name}/authorised_values":
216
"/authorised_value_categories/{authorised_value_category_name}/authorised_values":
3
  get:
217
  get:
4
    x-mojo-to: AuthorisedValues#list_av_from_category
218
    x-mojo-to: AuthorisedValues#list_av_from_category
Lines 66-72 Link Here
66
        schema:
280
        schema:
67
          $ref: "../swagger.yaml#/definitions/error"
281
          $ref: "../swagger.yaml#/definitions/error"
68
      404:
282
      404:
69
        description: Ressource not found
283
        description: Resource not found
70
        schema:
284
        schema:
71
          $ref: "../swagger.yaml#/definitions/error"
285
          $ref: "../swagger.yaml#/definitions/error"
72
      500:
286
      500:
(-)a/api/v1/swagger/swagger.yaml (+4 lines)
Lines 217-222 paths: Link Here
217
    $ref: ./paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id}~1domains
217
    $ref: ./paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id}~1domains
218
  "/auth/identity_providers/{identity_provider_id}/domains/{identity_provider_domain_id}":
218
  "/auth/identity_providers/{identity_provider_id}/domains/{identity_provider_domain_id}":
219
    $ref: ./paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id}~1domains~1{identity_provider_domain_id}
219
    $ref: ./paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id}~1domains~1{identity_provider_domain_id}
220
  "/authorised_values": 
221
    $ref: ./paths/authorised_values.yaml#/~1authorised_values
222
  "/authorised_values/{authorised_value_id}": 
223
    $ref: ./paths/authorised_values.yaml#/~1authorised_values~1{authorised_value_id}
220
  /authorised_value_categories:
224
  /authorised_value_categories:
221
    $ref: ./paths/authorised_value_categories.yaml#/~1authorised_value_categories
225
    $ref: ./paths/authorised_value_categories.yaml#/~1authorised_value_categories
222
  "/authorised_value_categories/{authorised_value_category_name}/authorised_values":
226
  "/authorised_value_categories/{authorised_value_category_name}/authorised_values":
(-)a/t/db_dependent/api/v1/authorised_values.t (-2 / +351 lines)
Lines 17-23 Link Here
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
19
20
use Test::More tests => 1;
20
use Test::More tests => 6;
21
use Test::Mojo;
21
use Test::Mojo;
22
22
23
use t::lib::TestBuilder;
23
use t::lib::TestBuilder;
Lines 85-87 subtest 'list_av_from_category() tests' => sub { Link Here
85
85
86
    $schema->storage->txn_rollback;
86
    $schema->storage->txn_rollback;
87
};
87
};
88
- 
88
89
subtest 'list() tests' => sub {
90
91
    plan tests => 20;
92
93
    $schema->storage->txn_begin;
94
95
    Koha::AuthorisedValues->search->delete;
96
97
    my $librarian = $builder->build_object(
98
        {
99
            class => 'Koha::Patrons',
100
            value => { flags => 2 ** 2 } # catalogue flag = 2
101
        }
102
    );
103
    my $password = 'thePassword123';
104
    $librarian->set_password( { password => $password, skip_validation => 1 } );
105
    my $userid = $librarian->userid;
106
107
    my $patron = $builder->build_object(
108
        {
109
            class => 'Koha::Patrons',
110
            value => { flags => 0 }
111
        }
112
    );
113
114
    $patron->set_password( { password => $password, skip_validation => 1 } );
115
    my $unauth_userid = $patron->userid;
116
117
    ## Authorized user tests
118
    # No AVs, so empty array should be returned
119
    $t->get_ok("//$userid:$password@/api/v1/authorised_values")
120
      ->status_is(200)
121
      ->json_is( [] );
122
123
    my $av = $builder->build_object({ class => 'Koha::AuthorisedValues' });
124
125
    # One av created, should get returned
126
    $t->get_ok("//$userid:$password@/api/v1/authorised_values")
127
      ->status_is(200)
128
      ->json_is( [$av->to_api] );
129
130
    my $another_av = $builder->build_object(
131
        { class => 'Koha::AuthorisedValues', value => { lib => $av->lib } } );
132
    my $av_with_another_lib = $builder->build_object({ class => 'Koha::AuthorisedValues' });
133
134
    # Two avs created, they should both be returned
135
    $t->get_ok("//$userid:$password@/api/v1/authorised_values")
136
      ->status_is(200)
137
      ->json_is([$av->to_api,
138
                 $another_av->to_api,
139
                 $av_with_another_lib->to_api
140
                 ] );
141
142
    # Filtering works, two avs sharing lib
143
    $t->get_ok("//$userid:$password@/api/v1/authorised_values?description=" . $av->lib )
144
      ->status_is(200)
145
      ->json_is([ $av->to_api,
146
                  $another_av->to_api
147
                  ]);
148
149
    $t->get_ok("//$userid:$password@/api/v1/authorised_values?value=" . $av->authorised_value )
150
      ->status_is(200)
151
      ->json_is( [$av->to_api] );
152
153
    # Warn on unsupported query parameter
154
    $t->get_ok("//$userid:$password@/api/v1/authorised_values?av_blah=blah" )
155
      ->status_is(400)
156
      ->json_is( [{ path => '/query/av_blah', message => 'Malformed query string'}] );
157
158
    # Unauthorized access
159
    $t->get_ok("//$unauth_userid:$password@/api/v1/authorised_values")
160
      ->status_is(403);
161
162
    $schema->storage->txn_rollback;
163
};
164
165
subtest 'get() tests' => sub {
166
167
    plan tests => 8;
168
169
    $schema->storage->txn_begin;
170
171
    my $av = $builder->build_object({ class => 'Koha::AuthorisedValues' });
172
    my $librarian = $builder->build_object(
173
        {
174
            class => 'Koha::Patrons',
175
            value => { flags => 2**2 }    # catalogue flag = 2
176
        }
177
    );
178
    my $password = 'thePassword123';
179
    $librarian->set_password( { password => $password, skip_validation => 1 } );
180
    my $userid = $librarian->userid;
181
182
    my $patron = $builder->build_object(
183
        {
184
            class => 'Koha::Patrons',
185
            value => { flags => 0 }
186
        }
187
    );
188
189
    $patron->set_password( { password => $password, skip_validation => 1 } );
190
    my $unauth_userid = $patron->userid;
191
192
    $t->get_ok( "//$userid:$password@/api/v1/authorised_values/" . $av->id )
193
      ->status_is(200)
194
      ->json_is($av->to_api);
195
196
    $t->get_ok( "//$unauth_userid:$password@/api/v1/authorised_values/" . $av->id )
197
      ->status_is(403);
198
199
    my $av_to_delete = $builder->build_object({ class => 'Koha::AuthorisedValues' });
200
    my $non_existent_id = $av_to_delete->id;
201
    $av_to_delete->delete;
202
203
    $t->get_ok( "//$userid:$password@/api/v1/authorised_values/$non_existent_id" )
204
      ->status_is(404)
205
      ->json_is( '/error' => 'Authorised value not found' );
206
207
    $schema->storage->txn_rollback;
208
};
209
210
subtest 'add() tests' => sub {
211
212
    plan tests => 18;
213
214
    $schema->storage->txn_begin;
215
216
    my $librarian = $builder->build_object(
217
        {
218
            class => 'Koha::Patrons',
219
            value => { flags => 2**3 }    # parameters flag = 2
220
        }
221
    );
222
    my $password = 'thePassword123';
223
    $librarian->set_password( { password => $password, skip_validation => 1 } );
224
    my $userid = $librarian->userid;
225
226
    my $patron = $builder->build_object(
227
        {
228
            class => 'Koha::Patrons',
229
            value => { flags => 0 }
230
        }
231
    );
232
233
    $patron->set_password( { password => $password, skip_validation => 1 } );
234
    my $unauth_userid = $patron->userid;
235
236
    my $av_cat = $builder->build_object({ class => 'Koha::AuthorisedValueCategories' });
237
    my $av = {
238
        category         => $av_cat->category_name,
239
        value            => "a value",
240
        description      => "a lib",
241
        opac_description => "opac lib"
242
    };
243
244
    # Unauthorized attempt to write
245
    $t->post_ok("//$unauth_userid:$password@/api/v1/authorised_values" => json => $av)
246
      ->status_is(403);
247
248
    # Authorized attempt to write invalid data
249
    my $av_with_invalid_field = {
250
        blah             => "Av Blah",
251
        category         => $av_cat->category_name,
252
        value            => "a value",
253
        description      => "a lib",
254
        opac_description => "opac lib"
255
    };
256
257
    $t->post_ok( "//$userid:$password@/api/v1/authorised_values" => json => $av_with_invalid_field )
258
      ->status_is(400)
259
      ->json_is(
260
        "/errors" => [
261
            {
262
                message => "Properties not allowed: blah.",
263
                path    => "/body"
264
            }
265
        ]
266
      );
267
268
    # Authorized attempt to write
269
    my $av_id =
270
      $t->post_ok( "//$userid:$password@/api/v1/authorised_values" => json => $av )
271
        ->status_is( 201, 'SWAGGER3.2.1' )
272
        ->header_like(
273
            Location => qr|^\/api\/v1\/authorised_values/\d*|,
274
            'SWAGGER3.4.1'
275
            )
276
        ->json_is( '/category'         => $av->{category} )
277
        ->json_is( '/value'            => $av->{value} )
278
        ->json_is( '/description'      => $av->{description} )
279
        ->json_is( '/opac_description' => $av->{opac_description} )
280
        ->tx->res->json->{authorised_value_id};
281
282
    # Authorized attempt to create with null id
283
    $av->{authorised_value_id} = undef;
284
    $t->post_ok( "//$userid:$password@/api/v1/authorised_values" => json => $av )
285
      ->status_is(400)
286
      ->json_has('/errors');
287
288
    # Authorized attempt to create with existing id
289
    $av->{authorised_value_id} = $av_id;
290
    $t->post_ok( "//$userid:$password@/api/v1/authorised_values" => json => $av )
291
      ->status_is(400)
292
      ->json_is(
293
        "/errors" => [
294
            {
295
                message => "Read-only.",
296
                path    => "/body/authorised_value_id"
297
            }
298
        ]
299
    );
300
301
    $schema->storage->txn_rollback;
302
};
303
304
subtest 'update() tests' => sub {
305
306
    plan tests => 15;
307
308
    $schema->storage->txn_begin;
309
310
    my $librarian = $builder->build_object(
311
        {
312
            class => 'Koha::Patrons',
313
            value => { flags => 2**3 }    # parameters flag = 2
314
        }
315
    );
316
    my $password = 'thePassword123';
317
    $librarian->set_password( { password => $password, skip_validation => 1 } );
318
    my $userid = $librarian->userid;
319
320
    my $patron = $builder->build_object(
321
        {
322
            class => 'Koha::Patrons',
323
            value => { flags => 0 }
324
        }
325
    );
326
327
    $patron->set_password( { password => $password, skip_validation => 1 } );
328
    my $unauth_userid = $patron->userid;
329
330
    my $av_id = $builder->build_object({ class => 'Koha::AuthorisedValues' } )->id;
331
332
    # Unauthorized attempt to update
333
    $t->put_ok( "//$unauth_userid:$password@/api/v1/authorised_values/$av_id" => json => { name => 'New unauthorized name change' } )
334
      ->status_is(403);
335
336
    my $av_cat = $builder->build_object({ class => 'Koha::AuthorisedValueCategories' });
337
338
    # Attempt partial update on a PUT
339
    my $av_with_missing_field = {
340
        category => $av_cat->category_name,
341
        value    => "a value",
342
    };
343
344
    $t->put_ok( "//$userid:$password@/api/v1/authorised_values/$av_id" => json => $av_with_missing_field )
345
      ->status_is(400)
346
      ->json_is( "/errors" =>
347
          [ { message => "Missing property.", path => "/body/description" } ]
348
      );
349
350
    # Full object update on PUT
351
    my $av_with_updated_field = {
352
        category    => $av_cat->category_name,
353
        value       => "a value",
354
        description => "a lib",
355
    };
356
357
    $t->put_ok( "//$userid:$password@/api/v1/authorised_values/$av_id" => json => $av_with_updated_field )
358
      ->status_is(200)
359
      ->json_is( '/description' => 'a lib' );
360
361
    # Authorized attempt to write invalid data
362
    my $av_with_invalid_field = {
363
        blah             => "Av Blah",
364
        category         => $av_cat->category_name,
365
        value            => "a value",
366
        description      => "a lib",
367
        opac_description => "opac lib"
368
    };
369
370
    $t->put_ok( "//$userid:$password@/api/v1/authorised_values/$av_id" => json => $av_with_invalid_field )
371
      ->status_is(400)
372
      ->json_is(
373
        "/errors" => [
374
            {
375
                message => "Properties not allowed: blah.",
376
                path    => "/body"
377
            }
378
        ]
379
    );
380
381
    my $av_to_delete = $builder->build_object({ class => 'Koha::AuthorisedValues' });
382
    my $non_existent_id = $av_to_delete->id;
383
    $av_to_delete->delete;
384
385
    $t->put_ok( "//$userid:$password@/api/v1/authorised_values/$non_existent_id" => json => $av_with_updated_field )
386
      ->status_is(404);
387
388
    # Wrong method (POST)
389
    $av_with_updated_field->{authorised_value_id} = 2;
390
391
    $t->post_ok( "//$userid:$password@/api/v1/authorised_values/$av_id" => json => $av_with_updated_field )
392
      ->status_is(404);
393
394
    $schema->storage->txn_rollback;
395
};
396
397
subtest 'delete() tests' => sub {
398
399
    plan tests => 7;
400
401
    $schema->storage->txn_begin;
402
403
    my $librarian = $builder->build_object(
404
        {
405
            class => 'Koha::Patrons',
406
            value => { flags => 2**3 }    # parameters flag = 2
407
        }
408
    );
409
    my $password = 'thePassword123';
410
    $librarian->set_password( { password => $password, skip_validation => 1 } );
411
    my $userid = $librarian->userid;
412
413
    my $patron = $builder->build_object(
414
        {
415
            class => 'Koha::Patrons',
416
            value => { flags => 0 }
417
        }
418
    );
419
420
    $patron->set_password( { password => $password, skip_validation => 1 } );
421
    my $unauth_userid = $patron->userid;
422
423
    my $av_id = $builder->build_object({ class => 'Koha::AuthorisedValues' })->id;
424
425
    # Unauthorized attempt to delete
426
    $t->delete_ok( "//$unauth_userid:$password@/api/v1/authorised_values/$av_id" )
427
      ->status_is(403);
428
429
    $t->delete_ok("//$userid:$password@/api/v1/authorised_values/$av_id")
430
      ->status_is(204, 'SWAGGER3.2.4')
431
      ->content_is('', 'SWAGGER3.3.4');
432
433
    $t->delete_ok("//$userid:$password@/api/v1/authorised_values/$av_id")
434
      ->status_is(404);
435
436
    $schema->storage->txn_rollback;
437
};

Return to bug 17390