diff options
-rw-r--r-- | cpanfile | 2 | ||||
-rw-r--r-- | cpanfile.snapshot | 13 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/FixMyStreet.pm | 1 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/TfL.pm | 14 | ||||
-rw-r--r-- | t/app/controller/admin/templates.t | 1 | ||||
-rw-r--r-- | t/cobrand/tfl.t | 73 |
6 files changed, 102 insertions, 2 deletions
@@ -131,6 +131,8 @@ requires 'YAML', '1.28'; feature 'uk', 'FixMyStreet.com specific requirements' => sub { # East Hampshire requires 'SOAP::Lite', '1.20'; + # TfL + requires 'Net::Subnet'; }; feature 'zurich', 'Zueri wie neu specific requirements' => sub { diff --git a/cpanfile.snapshot b/cpanfile.snapshot index ccb8bf1f6..85132bbb6 100644 --- a/cpanfile.snapshot +++ b/cpanfile.snapshot @@ -5424,6 +5424,13 @@ DISTRIBUTIONS POSIX 0 Socket 0 Time::HiRes 0 + Net-Subnet-1.03 + pathname: J/JU/JUERD/Net-Subnet-1.03.tar.gz + provides: + Net::Subnet 1.03 + requirements: + ExtUtils::MakeMaker 0 + Socket6 0.23 Net-Twitter-Lite-0.12008 pathname: M/MM/MMIMS/Net-Twitter-Lite-0.12008.tar.gz provides: @@ -6771,6 +6778,12 @@ DISTRIBUTIONS ExtUtils::Constant 0.23 ExtUtils::MakeMaker 0 perl 5.006001 + Socket6-0.29 + pathname: U/UM/UMEMOTO/Socket6-0.29.tar.gz + provides: + Socket6 0.29 + requirements: + ExtUtils::MakeMaker 0 Sort-Key-1.32 pathname: S/SA/SALVA/Sort-Key-1.32.tar.gz provides: diff --git a/perllib/FixMyStreet/Cobrand/FixMyStreet.pm b/perllib/FixMyStreet/Cobrand/FixMyStreet.pm index 5f5389e0d..f2551a16d 100644 --- a/perllib/FixMyStreet/Cobrand/FixMyStreet.pm +++ b/perllib/FixMyStreet/Cobrand/FixMyStreet.pm @@ -313,6 +313,7 @@ sub suppress_reporter_alerts { sub must_have_2fa { my ($self, $user) = @_; return 1 if $user->is_superuser; + return 1 if $user->from_body && $user->from_body->name eq 'TfL'; return 0; } diff --git a/perllib/FixMyStreet/Cobrand/TfL.pm b/perllib/FixMyStreet/Cobrand/TfL.pm index f4e7fb14a..4543c1751 100644 --- a/perllib/FixMyStreet/Cobrand/TfL.pm +++ b/perllib/FixMyStreet/Cobrand/TfL.pm @@ -127,4 +127,18 @@ sub available_permissions { return $perms; } +sub must_have_2fa { + my ($self, $user) = @_; + + require Net::Subnet; + my $ips = $self->feature('internal_ips'); + my $is_internal_network = Net::Subnet::subnet_matcher(@$ips); + + my $ip = $self->{c}->req->address; + return 'skip' if $is_internal_network->($ip); + return 1 if $user->is_superuser; + return 1 if $user->from_body && $user->from_body->name eq 'TfL'; + return 0; +} + 1; diff --git a/t/app/controller/admin/templates.t b/t/app/controller/admin/templates.t index ac915af94..ee477de20 100644 --- a/t/app/controller/admin/templates.t +++ b/t/app/controller/admin/templates.t @@ -330,6 +330,7 @@ subtest "category groups are shown" => sub { subtest "TfL cobrand only shows TfL templates" => sub { FixMyStreet::override_config { ALLOWED_COBRANDS => [ 'tfl' ], + COBRAND_FEATURES => { internal_ips => { tfl => [ '127.0.0.1' ] } }, }, sub { $report->update({ category => $tflcontact->category, diff --git a/t/cobrand/tfl.t b/t/cobrand/tfl.t index c7db294ac..6e6920c60 100644 --- a/t/cobrand/tfl.t +++ b/t/cobrand/tfl.t @@ -10,7 +10,7 @@ my $mech = FixMyStreet::TestMech->new; my $body = $mech->create_body_ok(2482, 'TfL'); my $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super User', is_superuser => 1); -my $staffuser = $mech->create_user_ok('counciluser@example.com', name => 'Council User', from_body => $body); +my $staffuser = $mech->create_user_ok('counciluser@example.com', name => 'Council User', from_body => $body, password => 'password'); $staffuser->user_body_permissions->create({ body => $body, permission_type => 'contribute_as_body', @@ -38,7 +38,8 @@ my $contact2 = $mech->create_contact_ok( FixMyStreet::override_config { ALLOWED_COBRANDS => 'tfl', - MAPIT_URL => 'http://mapit.uk/' + MAPIT_URL => 'http://mapit.uk/', + COBRAND_FEATURES => { internal_ips => { tfl => [ '127.0.0.1' ] } }, }, sub { subtest "test report creation and reference number" => sub { @@ -188,6 +189,74 @@ subtest 'Bromley staff cannot access TfL admin' => sub { }; FixMyStreet::override_config { + ALLOWED_COBRANDS => 'tfl', + MAPIT_URL => 'http://mapit.uk/', + COBRAND_FEATURES => { internal_ips => { tfl => [ '127.0.0.1' ] } }, +}, sub { + subtest 'On internal network, user not asked to sign up for 2FA' => sub { + $mech->get_ok('/auth'); + $mech->submit_form_ok( + { with_fields => { username => $staffuser->email, password_sign_in => 'password' } }, + "sign in using form" ); + $mech->content_contains('Your account'); + }; + subtest 'On internal network, user with 2FA not asked to enter it' => sub { + use Auth::GoogleAuth; + my $auth = Auth::GoogleAuth->new; + my $code = $auth->code; + + $staffuser->set_extra_metadata('2fa_secret', $auth->secret32); + $staffuser->update; + $mech->get_ok('/auth'); + $mech->submit_form_ok( + { with_fields => { username => $staffuser->email, password_sign_in => 'password' } }, + "sign in using form" ); + $mech->content_lacks('generate a two-factor code'); + $mech->content_contains('Your account'); + }; + subtest 'On internal network, cannot disable 2FA' => sub { + $mech->get_ok('/auth/generate_token'); + $mech->content_contains('Change two-factor'); + $mech->content_lacks('Deactivate two-factor'); + $staffuser->unset_extra_metadata('2fa_secret'); + $staffuser->update; + }; +}; +FixMyStreet::override_config { + ALLOWED_COBRANDS => 'tfl', + MAPIT_URL => 'http://mapit.uk/', +}, sub { + subtest 'On external network, user asked to sign up for 2FA' => sub { + $mech->get_ok('/auth'); + $mech->submit_form_ok( + { with_fields => { username => $staffuser->email, password_sign_in => 'password' } }, + "sign in using form" ); + $mech->content_contains('requires two-factor authentication'); + }; + subtest 'On external network, user with 2FA asked to enter it' => sub { + use Auth::GoogleAuth; + my $auth = Auth::GoogleAuth->new; + my $code = $auth->code; + + $staffuser->set_extra_metadata('2fa_secret', $auth->secret32); + $staffuser->update; + $mech->get_ok('/auth'); + $mech->submit_form_ok( + { with_fields => { username => $staffuser->email, password_sign_in => 'password' } }, + "sign in using form" ); + $mech->content_contains('Please generate a two-factor code'); + $mech->submit_form_ok({ with_fields => { '2fa_code' => $code } }, "provide correct 2FA code" ); + }; + subtest 'On external network, cannot disable 2FA' => sub { + $mech->get_ok('/auth/generate_token'); + $mech->content_contains('Change two-factor'); + $mech->content_lacks('Deactivate two-factor'); + $staffuser->unset_extra_metadata('2fa_secret'); + $staffuser->update; + }; +}; + +FixMyStreet::override_config { ALLOWED_COBRANDS => 'bromley', MAPIT_URL => 'http://mapit.uk/' }, sub { |