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

(-)a/t/db_dependent/api/v1/lists.t (-1 / +528 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/env perl
2
3
use Modern::Perl;
4
5
use Test::More tests => 5;
6
use Test::Mojo;
7
use Data::Dumper;
8
9
use JSON qw(encode_json);
10
11
use t::lib::TestBuilder;
12
use t::lib::Mocks;
13
14
use Koha::Virtualshelves;
15
use Koha::Database;
16
17
my $schema  = Koha::Database->new->schema;
18
my $builder = t::lib::TestBuilder->new;
19
20
my $t = Test::Mojo->new('Koha::REST::V1');
21
t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
22
23
subtest 'list() tests' => sub {
24
    plan tests => 7;
25
26
    $schema->storage->txn_begin;
27
28
    my $password = 'thePassword123';
29
30
    # Create librarian with necessary permissions
31
    my $librarian = $builder->build_object(
32
        {
33
            class => 'Koha::Patrons',
34
            value => { flags => 2**13 }
35
        }
36
    );
37
    my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
38
39
    $librarian->set_password( { password => $password, skip_validation => 1 } );
40
    $patron->set_password( { password => $password, skip_validation => 1 } );
41
42
    my $librarian_userid = $librarian->userid;
43
    my $patron_userid    = $patron->userid;
44
45
    # Create test lists owned by different users
46
    my $list_1 = $builder->build_object(
47
        {
48
            class => 'Koha::Virtualshelves',
49
            value => { owner => $librarian->id, public => 1 }
50
        }
51
    );
52
    my $list_2 = $builder->build_object(
53
        {
54
            class => 'Koha::Virtualshelves',
55
            value => { owner => $librarian->id, public => 0 }
56
        }
57
    );
58
59
    my $q = encode_json( { list_id => { -in => [ $list_1->id, $list_2->id, ] } } );
60
61
    # Test unauthorized access
62
    $t->get_ok("/api/v1/lists?q=$q")->status_is( 401, "Anonymous users cannot access admin lists endpoint" );
63
64
    $t->get_ok("//$patron_userid:$password@/api/v1/lists?q=$q")
65
        ->status_is( 403, "Regular patrons cannot access admin lists endpoint" );
66
67
    # Test authorized access - use to_api method which is already tested
68
    my $expected = [ $list_1->to_api, $list_2->to_api ];
69
70
    $t->get_ok("//$librarian_userid:$password@/api/v1/lists?q=$q")->status_is(200)->json_is($expected);
71
72
    $schema->storage->txn_rollback;
73
};
74
75
subtest 'get() tests' => sub {
76
    plan tests => 11;
77
78
    $schema->storage->txn_begin;
79
80
    my $password = 'thePassword123';
81
82
    # Create librarian with necessary permissions
83
    my $librarian = $builder->build_object(
84
        {
85
            class => 'Koha::Patrons',
86
            value => { flags => 2**13 }
87
        }
88
    );
89
    my $patron         = $builder->build_object( { class => 'Koha::Patrons' } );
90
    my $another_patron = $builder->build_object( { class => 'Koha::Patrons' } );
91
92
    $librarian->set_password( { password => $password, skip_validation => 1 } );
93
    $patron->set_password( { password => $password, skip_validation => 1 } );
94
95
    my $librarian_userid = $librarian->userid;
96
    my $patron_userid    = $patron->userid;
97
98
    # Create test lists with different attributes
99
    my $public_list = $builder->build_object(
100
        {
101
            class => 'Koha::Virtualshelves',
102
            value => {
103
                owner                   => $librarian->id,
104
                public                  => 1,
105
                allow_change_from_owner => 1
106
            }
107
        }
108
    );
109
110
    my $private_list = $builder->build_object(
111
        {
112
            class => 'Koha::Virtualshelves',
113
            value => {
114
                owner                   => $patron->id,
115
                public                  => 0,
116
                allow_change_from_owner => 0
117
            }
118
        }
119
    );
120
121
    my $another_private_list = $builder->build_object(
122
        {
123
            class => 'Koha::Virtualshelves',
124
            value => {
125
                owner                   => $another_patron->id,
126
                public                  => 0,
127
                allow_change_from_owner => 0
128
            }
129
        }
130
    );
131
132
    # Test unauthorized access
133
    $t->get_ok( "/api/v1/lists/" . $public_list->id )
134
        ->status_is( 401, "Anonymous users cannot access admin lists endpoint" );
135
136
    # Test access without permission
137
    $t->get_ok( "//$patron_userid:$password@/api/v1/lists/" . $public_list->id )
138
        ->status_is( 403, "Regular patrons cannot access admin lists endpoint" );
139
140
    # Test authorized access to public list
141
    $t->get_ok( "//$librarian_userid:$password@/api/v1/lists/" . $public_list->id )->status_is(200)
142
        ->json_is( $public_list->to_api );
143
144
    # Test authorized access to another patron's private list
145
    $t->get_ok( "//$librarian_userid:$password@/api/v1/lists/" . $private_list->id )->status_is(
146
        403,
147
        "Librarian cannot access private lists they don't own"
148
    );
149
150
    # Test non-existent list
151
    $t->get_ok("//$librarian_userid:$password@/api/v1/lists/99999999")->status_is( 404, "List not found" );
152
153
    $schema->storage->txn_rollback;
154
};
155
156
subtest 'add() tests' => sub {
157
    plan tests => 16;
158
159
    $schema->storage->txn_begin;
160
161
    my $password = 'thePassword123';
162
163
    # Create librarian with necessary permissions
164
    my $librarian = $builder->build_object(
165
        {
166
            class => 'Koha::Patrons',
167
            value => { flags => 2**13 }
168
        }
169
    );
170
    my $patron         = $builder->build_object( { class => 'Koha::Patrons' } );
171
    my $another_patron = $builder->build_object( { class => 'Koha::Patrons' } );
172
173
    $librarian->set_password( { password => $password, skip_validation => 1 } );
174
    $patron->set_password( { password => $password, skip_validation => 1 } );
175
176
    my $librarian_userid = $librarian->userid;
177
    my $patron_userid    = $patron->userid;
178
179
    # Test unauthorized access
180
    my $list_data = {
181
        name                    => "Test List",
182
        owner_id                => $librarian->id,
183
        public                  => 1,
184
        allow_change_from_owner => 1, allow_change_from_others => 0,
185
        default_sort_field      => 'title'
186
    };
187
188
    $t->post_ok( "/api/v1/lists" => json => $list_data )->status_is( 401, "Anonymous users cannot create lists" );
189
190
    $t->post_ok( "//$patron_userid:$password@/api/v1/lists" => json => $list_data )
191
        ->status_is( 403, "Regular patrons cannot create lists" );
192
193
    # Test authorized creation - list for self
194
    $t->post_ok( "//$librarian_userid:$password@/api/v1/lists" => json => $list_data )->status_is(201)->header_like(
195
        Location => qr|^/api/v1/lists/\d+|,
196
        'Location header is correct'
197
    )->json_has( '/list_id', 'List ID is present in response' )
198
        ->json_has( '/name', 'List name is present in response' );
199
200
    # Test authorized creation - list for another patron
201
    my $list_for_patron = {
202
        name                     => "Test List for Patron",
203
        owner_id                 => $another_patron->id,
204
        public                   => 0,
205
        allow_change_from_owner  => 1,
206
        allow_change_from_others => 0,
207
        default_sort_field       => 'title'
208
    };
209
210
    $t->post_ok( "//$librarian_userid:$password@/api/v1/lists" => json => $list_for_patron )->status_is(201)->json_is(
211
        '/owner_id' => $another_patron->id,
212
        'List created with correct owner'
213
    )->json_is( '/name' => 'Test List for Patron', 'List name set correctly' );
214
215
    # Test creating list with invalid owner_id
216
    my $list_invalid_owner = {
217
        name                     => "Test List",
218
        owner_id                 => 999999,        # Non-existent patron id
219
        public                   => 1,
220
        allow_change_from_owner  => 1,
221
        allow_change_from_others => 0,
222
        default_sort_field       => 'title'
223
    };
224
225
    $t->post_ok( "//$librarian_userid:$password@/api/v1/lists" => json => $list_invalid_owner )->status_is(400)
226
        ->json_like( '/error' => qr/Invalid owner_id/ );
227
228
    $schema->storage->txn_rollback;
229
};
230
231
subtest 'update() tests' => sub {
232
    plan tests => 27;
233
234
    $schema->storage->txn_begin;
235
236
    my $password = 'thePassword123';
237
238
    # Create librarian with necessary permissions
239
    my $librarian = $builder->build_object(
240
        {
241
            class => 'Koha::Patrons',
242
            value => { flags => 2**13 }
243
        }
244
    );
245
    my $patron         = $builder->build_object( { class => 'Koha::Patrons' } );
246
    my $another_patron = $builder->build_object( { class => 'Koha::Patrons' } );
247
248
    $librarian->set_password( { password => $password, skip_validation => 1 } );
249
    $patron->set_password( { password => $password, skip_validation => 1 } );
250
251
    my $librarian_userid = $librarian->userid;
252
    my $patron_userid    = $patron->userid;
253
254
    # Create test list
255
    my $list = $builder->build_object(
256
        {
257
            class => 'Koha::Virtualshelves',
258
            value => {
259
                owner                    => $librarian->id,
260
                public                   => 1,
261
                allow_change_from_owner  => 1,
262
                allow_change_from_others => 0
263
            }
264
        }
265
    );
266
267
    # Test unauthorized access
268
    my $update_data = {
269
        name                     => "Updated List Name 1",
270
        public                   => 0,
271
        allow_change_from_owner  => 1,
272
        allow_change_from_others => 0,
273
        default_sort_field       => 'title'
274
    };
275
276
    $t->put_ok( "/api/v1/lists/" . $list->id => json => $update_data )
277
        ->status_is( 401, "Anonymous users cannot update lists" );
278
279
    $t->put_ok( "//$patron_userid:$password@/api/v1/lists/" . $list->id => json => $update_data )
280
        ->status_is( 403, "Regular patrons cannot update lists" );
281
282
    # Test successful update
283
    $t->put_ok( "//$librarian_userid:$password@/api/v1/lists/" . $list->id => json => $update_data )->status_is(200)
284
        ->json_is(
285
        '/name' => 'Updated List Name 1',
286
        'List name updated correctly'
287
    )->json_is( '/public' => 0, 'List privacy updated correctly' );
288
289
    # Test update of non-existent list
290
    $t->put_ok( "//$librarian_userid:$password@/api/v1/lists/99999999" => json => $update_data )
291
        ->status_is( 404, "Attempting to update non-existent list returns 404" );
292
293
    # Test partial update - changed to include all required fields
294
    my $partial_update = {
295
        name                     => "Updated List Name 2",
296
        public                   => 1,
297
        allow_change_from_owner  => 1,
298
        allow_change_from_others => 0,
299
        default_sort_field       => 'title'
300
    };
301
302
    $t->put_ok( "//$librarian_userid:$password@/api/v1/lists/" . $list->id => json => $partial_update )->status_is(200)
303
        ->json_is( '/name' => "Updated List Name 2", "Update successful" );
304
305
    # Test updating another patron's list with librarian permissions
306
    my $patron_list = $builder->build_object(
307
        {
308
            class => 'Koha::Virtualshelves',
309
            value => {
310
                owner                    => $patron->id,
311
                public                   => 1,
312
                allow_change_from_owner  => 1,
313
                allow_change_from_others => 1,
314
                allow_change_from_staff  => 1
315
            }
316
        }
317
    );
318
319
    my $update_data_2 = {
320
        name                     => "Updated List Name 3",
321
        public                   => 0,
322
        allow_change_from_owner  => 1,
323
        allow_change_from_others => 0,
324
        default_sort_field       => 'title'
325
    };
326
327
    $t->put_ok( "//$librarian_userid:$password@/api/v1/lists/" . $patron_list->id => json => $update_data_2 )
328
        ->status_is(200)->json_is( '/name' => 'Updated List Name 3', 'Librarian can update other patron\'s list' );
329
330
    # Test librarian updating their own list
331
    my $librarian_list = $builder->build_object(
332
        {
333
            class => 'Koha::Virtualshelves',
334
            value => {
335
                owner                   => $librarian->id,
336
                public                  => 1,
337
                allow_change_from_owner => 0               # Even librarian should respect this flag for their own lists
338
            }
339
        }
340
    );
341
342
    $t->put_ok( "//$librarian_userid:$password@/api/v1/lists/" . $librarian_list->id => json => $update_data )
343
        ->status_is(
344
        403,
345
        "Even librarians must respect allow_change_from_owner for their own lists"
346
        );
347
348
    # Test update with allow_change_from_staff permission
349
    my $list_staff = $builder->build_object(
350
        {
351
            class => 'Koha::Virtualshelves',
352
            value => {
353
                owner                    => $patron->id,
354
                public                   => 1,
355
                allow_change_from_owner  => 1,
356
                allow_change_from_others => 0,
357
                allow_change_from_staff  => 1
358
            }
359
        }
360
    );
361
362
    my $update_data_3 = {
363
        name                     => "Updated List Name 4",
364
        public                   => 0,
365
        allow_change_from_owner  => 1,
366
        allow_change_from_others => 0,
367
        default_sort_field       => 'title'
368
    };
369
370
    $t->put_ok( "//$librarian_userid:$password@/api/v1/lists/" . $list_staff->id => json => $update_data_3 )
371
        ->status_is(200)
372
        ->json_is( '/name' => 'Updated List Name 4', 'Staff can update list with allow_change_from_staff' );
373
374
    # Test updating list with no permissions
375
    my $no_permission_list = $builder->build_object(
376
        {
377
            class => 'Koha::Virtualshelves',
378
            value => {
379
                owner                    => $patron->id,
380
                public                   => 1,
381
                allow_change_from_owner  => 1,
382
                allow_change_from_others => 0,
383
                allow_change_from_staff  => 0
384
            }
385
        }
386
    );
387
388
    my $update_data_4 = {
389
        name                     => "Updated List Name 5",
390
        public                   => 0,
391
        allow_change_from_owner  => 1,
392
        allow_change_from_others => 0,
393
        default_sort_field       => 'title'
394
    };
395
396
    $t->put_ok( "//$librarian_userid:$password@/api/v1/lists/" . $no_permission_list->id => json => $update_data_4 )
397
        ->status_is(403)->json_is( '/error' => 'Cannot modify list without proper permissions' );
398
399
    # Test update when both permission flags are false
400
    my $no_perm_list = $builder->build_object(
401
        {
402
            class => 'Koha::Virtualshelves',
403
            value => {
404
                owner                    => $patron->id,
405
                public                   => 1,
406
                allow_change_from_owner  => 1,
407
                allow_change_from_others => 0,
408
                allow_change_from_staff  => 0
409
            }
410
        }
411
    );
412
413
    $t->put_ok( "//$librarian_userid:$password@/api/v1/lists/" . $no_perm_list->id => json => $update_data )
414
        ->status_is(403)->json_is( '/error' => 'Cannot modify list without proper permissions' );
415
416
    $schema->storage->txn_rollback;
417
};
418
419
subtest 'delete() tests' => sub {
420
    plan tests => 16;
421
422
    $schema->storage->txn_begin;
423
424
    my $password = 'thePassword123';
425
426
    # Create librarian with necessary permissions
427
    my $librarian = $builder->build_object(
428
        {
429
            class => 'Koha::Patrons',
430
            value => { flags => 2**13 }
431
        }
432
    );
433
    my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
434
435
    $librarian->set_password( { password => $password, skip_validation => 1 } );
436
    $patron->set_password( { password => $password, skip_validation => 1 } );
437
438
    my $librarian_userid = $librarian->userid;
439
    my $patron_userid    = $patron->userid;
440
441
    # Create test list
442
    my $list = $builder->build_object(
443
        {
444
            class => 'Koha::Virtualshelves',
445
            value => { owner => $librarian->id }
446
        }
447
    );
448
449
    # Test unauthorized access
450
    $t->delete_ok( "/api/v1/lists/" . $list->id )->status_is( 401, "Anonymous users cannot delete lists" );
451
452
    $t->delete_ok( "//$patron_userid:$password@/api/v1/lists/" . $list->id )
453
        ->status_is( 403, "Regular patrons cannot delete lists" );
454
455
    # Test successful delete
456
    $t->delete_ok( "//$librarian_userid:$password@/api/v1/lists/" . $list->id )
457
        ->status_is( 204, "List deleted successfully" );
458
459
    # Test non-existent list
460
    $t->delete_ok("//$librarian_userid:$password@/api/v1/lists/99999999")
461
        ->status_is( 404, "Attempting to delete non-existent list returns 404" );
462
463
    # Test deleting another patron's list with librarian permissions
464
    my $patron_list = $builder->build_object(
465
        {
466
            class => 'Koha::Virtualshelves',
467
            value => { owner => $patron->id }
468
        }
469
    );
470
471
    $t->delete_ok( "//$librarian_userid:$password@/api/v1/lists/" . $patron_list->id )
472
        ->status_is( 204, "Librarian can delete other patron's list" );
473
474
    # Test deleting list with allow_change_from_staff permission
475
    my $list_staff = $builder->build_object(
476
        {
477
            class => 'Koha::Virtualshelves',
478
            value => {
479
                owner                    => $patron->id,
480
                public                   => 1,
481
                allow_change_from_owner  => 1,
482
                allow_change_from_others => 0,
483
                allow_change_from_staff  => 1
484
            }
485
        }
486
    );
487
488
    $t->delete_ok( "//$librarian_userid:$password@/api/v1/lists/" . $list_staff->id )
489
        ->status_is( 204, "Staff can delete list with allow_change_from_staff" );
490
491
    # Test deleting list with allow_change_from_others permission
492
    my $list_others = $builder->build_object(
493
        {
494
            class => 'Koha::Virtualshelves',
495
            value => {
496
                owner                    => $patron->id,
497
                public                   => 1,
498
                allow_change_from_owner  => 1,
499
                allow_change_from_others => 1,
500
                allow_change_from_staff  => 0
501
            }
502
        }
503
    );
504
505
    $t->delete_ok( "//$librarian_userid:$password@/api/v1/lists/" . $list_others->id )
506
        ->status_is( 204, "Can delete list with allow_change_from_others" );
507
508
    # Test deleting list with no permissions
509
    my $no_permission_list = $builder->build_object(
510
        {
511
            class => 'Koha::Virtualshelves',
512
            value => {
513
                owner                    => $patron->id,
514
                public                   => 1,
515
                allow_change_from_owner  => 1,
516
                allow_change_from_others => 0,
517
                allow_change_from_staff  => 0
518
            }
519
        }
520
    );
521
522
    $t->delete_ok( "//$librarian_userid:$password@/api/v1/lists/" . $no_permission_list->id )
523
        ->status_is( 403, "Cannot delete list without proper permissions" );
524
525
    $schema->storage->txn_rollback;
526
};
527
528
1;

Return to bug 38050