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

(-)a/t/db_dependent/selenium/authentication_2fa.t (-7 / +105 lines)
Lines 18-24 Link Here
18
use Modern::Perl;
18
use Modern::Perl;
19
use utf8;
19
use utf8;
20
use Test::NoWarnings;
20
use Test::NoWarnings;
21
use Test::More tests => 6;
21
use Test::More tests => 7;
22
22
23
use C4::Context;
23
use C4::Context;
24
use Koha::AuthUtils;
24
use Koha::AuthUtils;
Lines 37-51 SKIP: { Link Here
37
    my $builder = t::lib::TestBuilder->new;
37
    my $builder = t::lib::TestBuilder->new;
38
38
39
    my $library_name = 'my ❤ library';
39
    my $library_name = 'my ❤ library';
40
    my $library = $builder->build_object( { class => 'Koha::Libraries', value => { branchname => $library_name } } );
40
    my $library  = $builder->build_object( { class => 'Koha::Libraries', value => { branchname => $library_name } } );
41
    my $patron  = $builder->build_object(
41
    my $category = $builder->build_object( { class => 'Koha::Patron::Categories' } );
42
        { class => 'Koha::Patrons', value => { flags => 1, branchcode => $library->branchcode } } );
42
    my $patron   = $builder->build_object(
43
        {
44
            class => 'Koha::Patrons',
45
            value => { flags => 1, branchcode => $library->branchcode, categorycode => $category->categorycode }
46
        }
47
    );
43
    $patron->flags(1)->store;    # superlibrarian permission
48
    $patron->flags(1)->store;    # superlibrarian permission
44
    my $password = Koha::AuthUtils::generate_password( $patron->category );
49
    my $password = Koha::AuthUtils::generate_password( $patron->category );
45
    t::lib::Mocks::mock_preference( 'RequireStrongPassword', 0 );
50
    t::lib::Mocks::mock_preference( 'RequireStrongPassword', 0 );
46
    $patron->set_password( { password => $password } );
51
    $patron->set_password( { password => $password } );
47
52
48
    push @data_to_cleanup, $patron, $patron->category, $patron->library;
53
    push @data_to_cleanup, $category, $library, $patron;
49
54
50
    my $s      = t::lib::Selenium->new( { login => $patron->userid, password => $password } );
55
    my $s      = t::lib::Selenium->new( { login => $patron->userid, password => $password } );
51
    my $driver = $s->driver;
56
    my $driver = $s->driver;
Lines 359-369 SKIP: { Link Here
359
        is( $patron->auth_method(), 'password', 'auth_method has been reset to "password"' );
364
        is( $patron->auth_method(), 'password', 'auth_method has been reset to "password"' );
360
    };
365
    };
361
366
367
    subtest "Managing other users' 2FA" => sub {
368
369
        plan tests => 2;
370
371
        C4::Context->set_preference( 'TwoFactorAuthentication', 'enabled' );
372
373
        # Create a staff user with minimal permissions and set up 2FA
374
        my $staff_user = $builder->build_object(
375
            {
376
                class => 'Koha::Patrons',
377
                value => { flags => 4, branchcode => $library->branchcode, categorycode => $category->categorycode }
378
            }    # cataloguing permission only
379
        );
380
        my $staff_password = Koha::AuthUtils::generate_password( $staff_user->category );
381
        t::lib::Mocks::mock_preference( 'RequireStrongPassword', 0 );
382
        $staff_user->set_password( { password => $staff_password } );
383
        push @data_to_cleanup, $staff_user;
384
385
        # Set up 2FA for staff user the same way as previous tests
386
        my $mainpage = $s->base_url . q|mainpage.pl|;
387
        $driver->get( $mainpage . q|?logout.x=1| );
388
        $s->fill_form( { userid => $staff_user->userid, password => $staff_password } );
389
        $driver->find_element('//input[@id="submit-button"]')->click;
390
391
        $driver->get( $s->base_url . q|members/two_factor_auth.pl| );
392
        $driver->find_element('//*[@id="enable-2FA"]')->click;
393
        $s->wait_for_ajax;
394
395
        my $secret32 = $driver->find_element('//*[@id="secret32"]')->get_value();
396
        my $auth     = Koha::Auth::TwoFactorAuth->new( { patron => $staff_user, secret32 => $secret32 } );
397
        my $code     = $auth->code();
398
        $driver->find_element('//*[@id="pin_code"]')->send_keys($code);
399
        $driver->find_element('//*[@id="register-2FA"]')->click;
400
        $s->wait_for_ajax;
401
402
        subtest "Non-superlibrarian denied" => sub {
403
            plan tests => 1;
404
405
            # Try to access another user's 2FA page - should get 403
406
            $driver->get( $s->base_url . q|members/two_factor_auth.pl?borrowernumber=| . $patron->borrowernumber );
407
            like(
408
                $driver->get_title, qr(Error 403),
409
                'Non-superlibrarian gets 403 when trying to manage other user 2FA'
410
            );
411
        };
412
413
        subtest "Superlibrarian can reset" => sub {
414
            plan tests => 4;
415
416
            # Create superlibrarian user
417
            my $admin_user = $builder->build_object(
418
                {
419
                    class => 'Koha::Patrons',
420
                    value => { flags => 1, branchcode => $library->branchcode, categorycode => $category->categorycode }
421
                }
422
            );
423
            my $admin_password = Koha::AuthUtils::generate_password( $admin_user->category );
424
            $admin_user->set_password( { password => $admin_password } );
425
            push @data_to_cleanup, $admin_user;
426
427
            # Login as superlibrarian
428
            $driver->get( $mainpage . q|?logout.x=1| );
429
            $s->fill_form( { userid => $admin_user->userid, password => $admin_password } );
430
            $driver->find_element('//input[@id="submit-button"]')->click;
431
432
            # Access staff user's 2FA management page
433
            $driver->get( $s->base_url . q|members/two_factor_auth.pl?borrowernumber=| . $staff_user->borrowernumber );
434
            like( $driver->get_title, qr(Two-factor authentication), 'Superlibrarian can access other user 2FA page' );
435
436
            # Verify 2FA is enabled for the staff user
437
            is(
438
                $driver->find_element(
439
                    '//div[@id="registration-status-enabled"]/div[@class="alert alert-success two-factor-status"]')
440
                    ->get_text,
441
                "Two-factor authentication: Enabled\n"
442
                    . $staff_user->firstname . " "
443
                    . $staff_user->surname
444
                    . " has two-factor authentication enabled for enhanced account security.",
445
                'Shows enabled status for staff user'
446
            );
447
448
            # Disable 2FA for the staff user
449
            $driver->find_element('//form[@id="two-factor-auth"]//input[@type="submit"]')->click;
450
451
            # Verify 2FA was disabled
452
            $staff_user = $staff_user->get_from_storage;
453
            is( $staff_user->secret,        undef,      "Staff user's secret has been cleared by superlibrarian" );
454
            is( $staff_user->auth_method(), 'password', 'Staff user auth_method reset to password' );
455
        };
456
    };
457
362
    $driver->quit();
458
    $driver->quit();
363
}
459
}
364
460
365
END {
461
END {
366
    $_->delete for @data_to_cleanup;
462
    # Clean up in reverse order to handle foreign key constraints
463
    for my $data ( reverse @data_to_cleanup ) {
464
        $data->delete if $data->in_storage;
465
    }
367
    C4::Context->set_preference( 'TwoFactorAuthentication', $pref_value );
466
    C4::Context->set_preference( 'TwoFactorAuthentication', $pref_value );
368
}
467
}
369
468
370
- 

Return to bug 41038