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

(-)a/t/db_dependent/api/v1/public/lists.t (-53 / +376 lines)
Lines 18-24 Link Here
18
use Modern::Perl;
18
use Modern::Perl;
19
19
20
use Test::NoWarnings;
20
use Test::NoWarnings;
21
use Test::More tests => 2;
21
use Test::More tests => 6;
22
use Test::Mojo;
22
use Test::Mojo;
23
23
24
use JSON qw(encode_json);
24
use JSON qw(encode_json);
Lines 52-124 subtest 'list_public() tests' => sub { Link Here
52
    $patron_2->set_password( { password => $password, skip_validation => 1 } );
52
    $patron_2->set_password( { password => $password, skip_validation => 1 } );
53
    my $patron_2_userid = $patron_2->userid;
53
    my $patron_2_userid = $patron_2->userid;
54
54
55
    my $list_1 =
55
    my $list_1 = $builder->build_object(
56
        $builder->build_object( { class => 'Koha::Virtualshelves', value => { owner => $patron_1->id, public => 1 } } );
57
    my $list_2 =
58
        $builder->build_object( { class => 'Koha::Virtualshelves', value => { owner => $patron_1->id, public => 0 } } );
59
    my $list_3 =
60
        $builder->build_object( { class => 'Koha::Virtualshelves', value => { owner => $patron_2->id, public => 1 } } );
61
    my $list_4 =
62
        $builder->build_object( { class => 'Koha::Virtualshelves', value => { owner => $patron_2->id, public => 0 } } );
63
64
    my $q = encode_json(
65
        {
56
        {
66
            list_id => {
57
            class => 'Koha::Virtualshelves',
67
                -in => [
58
            value => { owner => $patron_1->id, public => 1 }
68
                    $list_1->id,
59
        }
69
                    $list_2->id,
60
    );
70
                    $list_3->id,
61
    my $list_2 = $builder->build_object(
71
                    $list_4->id,
62
        {
72
                ]
63
            class => 'Koha::Virtualshelves',
73
            }
64
            value => { owner => $patron_1->id, public => 0 }
65
        }
66
    );
67
    my $list_3 = $builder->build_object(
68
        {
69
            class => 'Koha::Virtualshelves',
70
            value => { owner => $patron_2->id, public => 1 }
71
        }
72
    );
73
    my $list_4 = $builder->build_object(
74
        {
75
            class => 'Koha::Virtualshelves',
76
            value => { owner => $patron_2->id, public => 0 }
74
        }
77
        }
75
    );
78
    );
76
79
80
    my $q = encode_json( { list_id => { -in => [ $list_1->id, $list_2->id, $list_3->id, $list_4->id, ] } } );
81
77
    # anonymous
82
    # anonymous
78
    $t->get_ok("/api/v1/public/lists?q=$q")->status_is( 200, "Anonymous users can only fetch public lists" )
83
    $t->get_ok("/api/v1/public/lists?q=$q")->status_is( 200, "Anonymous users can only fetch public lists" )->json_is(
79
        ->json_is( [ $list_1->to_api( { public => 1 } ), $list_3->to_api( { public => 1 } ) ] );
84
        [
85
            $list_1->to_api( { public => 1 } ),
86
            $list_3->to_api( { public => 1 } )
87
        ]
88
    );
80
89
81
    $t->get_ok("/api/v1/public/lists?q=$q&only_public=1")
90
    $t->get_ok("/api/v1/public/lists?q=$q&only_public=1")
82
        ->status_is( 200, "Anonymous users can only fetch public lists" )
91
        ->status_is( 200, "Anonymous users can only fetch public lists" )->json_is(
83
        ->json_is( [ $list_1->to_api( { public => 1 } ), $list_3->to_api( { public => 1 } ) ] );
92
        [
93
            $list_1->to_api( { public => 1 } ),
94
            $list_3->to_api( { public => 1 } )
95
        ]
96
        );
84
97
85
    $t->get_ok("/api/v1/public/lists?q=$q&only_mine=1")
98
    $t->get_ok("/api/v1/public/lists?q=$q&only_mine=1")->status_is(
86
        ->status_is( 400, "Passing only_mine on an anonymous session generates a 400 code" )
99
        400,
87
        ->json_is( '/error_code' => q{only_mine_forbidden} );
100
        "Passing only_mine on an anonymous session generates a 400 code"
101
    )->json_is( '/error_code' => q{only_mine_forbidden} );
88
102
89
    $t->get_ok("//$patron_1_userid:$password@/api/v1/public/lists?q=$q&only_mine=1")
103
    $t->get_ok("//$patron_1_userid:$password@/api/v1/public/lists?q=$q&only_mine=1")->status_is(
90
        ->status_is( 200, "Passing only_mine with a logged in user makes it return only their lists" )
104
        200,
91
        ->json_is( [ $list_1->to_api( { public => 1 } ), $list_2->to_api( { public => 1 } ) ] );
105
        "Passing only_mine with a logged in user makes it return only their lists"
106
    )->json_is(
107
        [
108
            $list_1->to_api( { public => 1 } ),
109
            $list_2->to_api( { public => 1 } )
110
        ]
111
    );
92
112
93
    $t->get_ok("//$patron_2_userid:$password@/api/v1/public/lists?q=$q&only_mine=1")
113
    $t->get_ok("//$patron_2_userid:$password@/api/v1/public/lists?q=$q&only_mine=1")->status_is(
94
        ->status_is( 200, "Passing only_mine with a logged in user makes it return only their lists" )
114
        200,
95
        ->json_is( [ $list_3->to_api( { public => 1 } ), $list_4->to_api( { public => 1 } ) ] );
115
        "Passing only_mine with a logged in user makes it return only their lists"
116
    )->json_is(
117
        [
118
            $list_3->to_api( { public => 1 } ),
119
            $list_4->to_api( { public => 1 } )
120
        ]
121
    );
96
122
97
    # only public
123
    # only public
98
    $t->get_ok("//$patron_1_userid:$password@/api/v1/public/lists?q=$q&only_public=1")
124
    $t->get_ok("//$patron_1_userid:$password@/api/v1/public/lists?q=$q&only_public=1")->status_is(
99
        ->status_is( 200, "Passing only_public with a logged in user makes it return only public lists" )
125
        200,
100
        ->json_is( [ $list_1->to_api( { public => 1 } ), $list_3->to_api( { public => 1 } ) ] );
126
        "Passing only_public with a logged in user makes it return only public lists"
101
127
    )->json_is(
102
    $t->get_ok("//$patron_2_userid:$password@/api/v1/public/lists?q=$q&only_public=1")
128
        [
103
        ->status_is( 200, "Passing only_public with a logged in user makes it return only public lists" )
129
            $list_1->to_api( { public => 1 } ),
104
        ->json_is( [ $list_1->to_api( { public => 1 } ), $list_3->to_api( { public => 1 } ) ] );
130
            $list_3->to_api( { public => 1 } )
105
131
        ]
106
    $t->get_ok("//$patron_1_userid:$password@/api/v1/public/lists?q=$q")
132
    );
107
        ->status_is( 200, "Not filtering with only_mine or only_public makes it return all accessible lists" )
133
108
        ->json_is(
134
    $t->get_ok("//$patron_2_userid:$password@/api/v1/public/lists?q=$q&only_public=1")->status_is(
109
        [ $list_1->to_api( { public => 1 } ), $list_2->to_api( { public => 1 } ), $list_3->to_api( { public => 1 } ) ]
135
        200,
136
        "Passing only_public with a logged in user makes it return only public lists"
137
    )->json_is(
138
        [
139
            $list_1->to_api( { public => 1 } ),
140
            $list_3->to_api( { public => 1 } )
141
        ]
142
    );
143
144
    $t->get_ok("//$patron_1_userid:$password@/api/v1/public/lists?q=$q")->status_is(
145
        200,
146
        "Not filtering with only_mine or only_public makes it return all accessible lists"
147
    )->json_is(
148
        [
149
            $list_1->to_api( { public => 1 } ),
150
            $list_2->to_api( { public => 1 } ),
151
            $list_3->to_api( { public => 1 } )
152
        ]
153
    );
154
155
    $t->get_ok("//$patron_2_userid:$password@/api/v1/public/lists?q=$q")->status_is(
156
        200,
157
        "Not filtering with only_mine or only_public makes it return all accessible lists"
158
    )->json_is(
159
        [
160
            $list_1->to_api( { public => 1 } ),
161
            $list_3->to_api( { public => 1 } ),
162
            $list_4->to_api( { public => 1 } )
163
        ]
164
    );
165
166
    # conflicting params
167
    $t->get_ok("//$patron_1_userid:$password@/api/v1/public/lists?q=$q&only_public=1&only_mine=1")->status_is(
168
        200,
169
        "Passing only_public with a logged in user makes it return only public lists"
170
    )->json_is( [ $list_1->to_api( { public => 1 } ) ] );
171
172
    $schema->storage->txn_rollback;
173
};
174
175
subtest 'public_get() tests' => sub {
176
    plan tests => 12;
177
178
    $schema->storage->txn_begin;
179
180
    my $password = 'thePassword123';
181
    my $patron_1 = $builder->build_object( { class => 'Koha::Patrons' } );
182
    my $patron_2 = $builder->build_object( { class => 'Koha::Patrons' } );
183
184
    $patron_1->set_password( { password => $password, skip_validation => 1 } );
185
    $patron_2->set_password( { password => $password, skip_validation => 1 } );
186
187
    my $patron_1_userid = $patron_1->userid;
188
    my $patron_2_userid = $patron_2->userid;
189
190
    # Create test lists
191
    my $public_list = $builder->build_object(
192
        {
193
            class => 'Koha::Virtualshelves',
194
            value => {
195
                owner                   => $patron_1->id,
196
                public                  => 1,
197
                allow_change_from_owner => 1
198
            }
199
        }
200
    );
201
202
    my $private_list = $builder->build_object(
203
        {
204
            class => 'Koha::Virtualshelves',
205
            value => {
206
                owner                   => $patron_1->id,
207
                public                  => 0,
208
                allow_change_from_owner => 0
209
            }
210
        }
211
    );
212
213
    # Test anonymous access to public list
214
    $t->get_ok( "/api/v1/public/lists/" . $public_list->id )->status_is(200)->json_is( $public_list->to_api );
215
216
    # Test anonymous access to private list
217
    $t->get_ok( "/api/v1/public/lists/" . $private_list->id )
218
        ->status_is( 403, 'Anonymous user cannot access private list' );
219
220
    # Test authenticated access - owner can see their private list
221
    $t->get_ok( "//$patron_1_userid:$password@/api/v1/public/lists/" . $private_list->id )->status_is(200)
222
        ->json_is( $private_list->to_api );
223
224
    # Test non-owner access to private list
225
    $t->get_ok( "//$patron_2_userid:$password@/api/v1/public/lists/" . $private_list->id )
226
        ->status_is( 403, 'Non-owner cannot access private list' );
227
228
    # Test non-existent list
229
    $t->get_ok("/api/v1/public/lists/99999999")->status_is( 404, "List not found" );
230
231
    $schema->storage->txn_rollback;
232
};
233
234
subtest 'public_add() tests' => sub {
235
    plan tests => 9;    # Reduced test count since we're removing one assertion
236
237
    $schema->storage->txn_begin;
238
239
    my $password       = 'thePassword123';
240
    my $patron         = $builder->build_object( { class => 'Koha::Patrons' } );
241
    my $another_patron = $builder->build_object( { class => 'Koha::Patrons' } );
242
    $patron->set_password( { password => $password, skip_validation => 1 } );
243
    my $patron_userid = $patron->userid;
244
245
    my $list_data = {
246
        name                     => "Test List",
247
        public                   => 1,
248
        allow_change_from_owner  => 1,
249
        allow_change_from_others => 0,
250
        default_sort_field       => 'title'
251
    };
252
253
    # Test anonymous attempt
254
    $t->post_ok( "/api/v1/public/lists" => json => $list_data )->status_is( 401, 'Anonymous user cannot create list' );
255
256
    # Test authenticated user can create list
257
    $t->post_ok( "//$patron_userid:$password@/api/v1/public/lists" => json => $list_data )->status_is(201)
258
        ->json_has( '/list_id', 'List ID is present in response' )
259
        ->json_has( '/name',    'List name is present in response' )->json_is(
260
        '/owner_id' => $patron->id,
261
        'List created with logged in user as owner'
110
        );
262
        );
111
263
112
    $t->get_ok("//$patron_2_userid:$password@/api/v1/public/lists?q=$q")
264
    # Test attempt to specify owner_id
113
        ->status_is( 200, "Not filtering with only_mine or only_public makes it return all accessible lists" )
265
    my $list_with_owner = {
114
        ->json_is(
266
        name                     => "Test List",
115
        [ $list_1->to_api( { public => 1 } ), $list_3->to_api( { public => 1 } ), $list_4->to_api( { public => 1 } ) ]
267
        owner_id                 => $another_patron->id,    # Should be rejected
268
        public                   => 1,
269
        allow_change_from_owner  => 1,
270
        allow_change_from_others => 0,
271
        default_sort_field       => 'title'
272
    };
273
274
    $t->post_ok( "//$patron_userid:$password@/api/v1/public/lists" => json => $list_with_owner )->status_is(400);
275
276
    $schema->storage->txn_rollback;
277
};
278
279
subtest 'public_update() tests' => sub {
280
    plan tests => 15;
281
282
    $schema->storage->txn_begin;
283
284
    my $password       = 'thePassword123';
285
    my $patron         = $builder->build_object( { class => 'Koha::Patrons' } );
286
    my $another_patron = $builder->build_object( { class => 'Koha::Patrons' } );
287
288
    $patron->set_password( { password => $password, skip_validation => 1 } );
289
    $another_patron->set_password( { password => $password, skip_validation => 1 } );
290
291
    my $patron_userid         = $patron->userid;
292
    my $another_patron_userid = $another_patron->userid;
293
294
    # Create a list that can be modified
295
    my $modifiable_list = $builder->build_object(
296
        {
297
            class => 'Koha::Virtualshelves',
298
            value => {
299
                owner                   => $patron->id,
300
                public                  => 1,
301
                allow_change_from_owner => 1
302
            }
303
        }
304
    );
305
306
    # Create a list that cannot be modified
307
    my $unmodifiable_list = $builder->build_object(
308
        {
309
            class => 'Koha::Virtualshelves',
310
            value => {
311
                owner                   => $patron->id,
312
                public                  => 1,
313
                allow_change_from_owner => 0
314
            }
315
        }
316
    );
317
318
    my $update_data = {
319
        name                     => "Updated List Name",
320
        public                   => 0,
321
        allow_change_from_owner  => 1,
322
        allow_change_from_others => 0,
323
        default_sort_field       => 'title'
324
    };
325
326
    # Test anonymous attempt
327
    $t->put_ok( "/api/v1/public/lists/" . $modifiable_list->id => json => $update_data )
328
        ->status_is( 401, 'Anonymous user cannot update list' );
329
330
    # Test non-owner update attempt
331
    $t->put_ok(
332
        "//$another_patron_userid:$password@/api/v1/public/lists/" . $modifiable_list->id => json => $update_data )
333
        ->status_is( 403, 'Non-owner cannot update list' );
334
335
    # Test owner update success
336
    $t->put_ok( "//$patron_userid:$password@/api/v1/public/lists/" . $modifiable_list->id => json => $update_data )
337
        ->status_is(200)->json_is( '/name' => 'Updated List Name', 'List name updated' )
338
        ->json_is( '/public' => 0, 'List privacy updated' );
339
340
    # Test update of non-existent list
341
    $t->put_ok( "//$patron_userid:$password@/api/v1/public/lists/99999999" => json => $update_data )
342
        ->status_is( 404, "List not found" );
343
344
    # Test update of unmodifiable list
345
    $t->put_ok( "//$patron_userid:$password@/api/v1/public/lists/" . $unmodifiable_list->id => json => $update_data )
346
        ->status_is(
347
        403,
348
        "Cannot update list when allow_change_from_owner is false"
349
    )->json_is( '/error_code' => 'forbidden', 'Correct error code returned' );
350
351
    # Create librarian with necessary permissions
352
    my $librarian = $builder->build_object(
353
        {
354
            class => 'Koha::Patrons',
355
            value => { flags => 2**13 }
356
        }
357
    );
358
    $librarian->set_password( { password => $password, skip_validation => 1 } );
359
    my $librarian_userid = $librarian->userid;
360
361
    # Test librarian using public endpoint
362
    $t->put_ok( "//$librarian_userid:$password@/api/v1/public/lists/" . $modifiable_list->id => json => $update_data )
363
        ->status_is(
364
        403,
365
        'Librarian must use admin endpoint to modify others lists'
116
        );
366
        );
117
367
118
    # conflicting params
368
    $schema->storage->txn_rollback;
119
    $t->get_ok("//$patron_1_userid:$password@/api/v1/public/lists?q=$q&only_public=1&only_mine=1")
369
};
120
        ->status_is( 200, "Passing only_public with a logged in user makes it return only public lists" )
370
121
        ->json_is( [ $list_1->to_api( { public => 1 } ) ] );
371
subtest 'public_delete() tests' => sub {
372
    plan tests => 12;
373
374
    $schema->storage->txn_begin;
375
376
    my $password       = 'thePassword123';
377
    my $patron         = $builder->build_object( { class => 'Koha::Patrons' } );
378
    my $another_patron = $builder->build_object( { class => 'Koha::Patrons' } );
379
380
    $patron->set_password( { password => $password, skip_validation => 1 } );
381
    $another_patron->set_password( { password => $password, skip_validation => 1 } );
382
383
    my $patron_userid         = $patron->userid;
384
    my $another_patron_userid = $another_patron->userid;
385
386
    # Create test lists for different scenarios
387
    my $modifiable_list = $builder->build_object(
388
        {
389
            class => 'Koha::Virtualshelves',
390
            value => {
391
                owner                   => $patron->id,
392
                public                  => 1,
393
                allow_change_from_owner => 1
394
            }
395
        }
396
    );
397
398
    my $other_patron_list = $builder->build_object(
399
        {
400
            class => 'Koha::Virtualshelves',
401
            value => {
402
                owner                   => $another_patron->id,
403
                public                  => 1,
404
                allow_change_from_owner => 1
405
            }
406
        }
407
    );
408
409
    my $unmodifiable_list = $builder->build_object(
410
        {
411
            class => 'Koha::Virtualshelves',
412
            value => {
413
                owner                   => $patron->id,
414
                public                  => 1,
415
                allow_change_from_owner => 0
416
            }
417
        }
418
    );
419
420
    # Test anonymous attempt
421
    $t->delete_ok( "/api/v1/public/lists/" . $modifiable_list->id )
422
        ->status_is( 401, 'Anonymous user cannot delete list' );
423
424
    # Test non-owner delete attempt
425
    $t->delete_ok( "//$another_patron_userid:$password@/api/v1/public/lists/" . $modifiable_list->id )
426
        ->status_is( 403, 'Non-owner cannot delete list' );
427
428
    # Test attempt to delete another patron's list
429
    $t->delete_ok( "//$patron_userid:$password@/api/v1/public/lists/" . $other_patron_list->id )
430
        ->status_is( 403, "Cannot delete another patron's list" );
431
432
    # Test delete of unmodifiable list
433
    $t->delete_ok( "//$patron_userid:$password@/api/v1/public/lists/" . $unmodifiable_list->id )->status_is(
434
        403,
435
        "Cannot delete list when allow_change_from_owner is false"
436
    );
437
438
    # Test delete of non-existent list
439
    $t->delete_ok("//$patron_userid:$password@/api/v1/public/lists/99999999")->status_is( 404, "List not found" );
440
441
    # Test successful delete by owner
442
    $t->delete_ok( "//$patron_userid:$password@/api/v1/public/lists/" . $modifiable_list->id )
443
        ->status_is( 204, 'List deleted successfully' );
122
444
123
    $schema->storage->txn_rollback;
445
    $schema->storage->txn_rollback;
124
};
446
};
125
- 
447
448
1;

Return to bug 38050