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

Return to bug 38050