diff options
-rw-r--r-- | CHANGELOG.md | 3 | ||||
-rw-r--r-- | perllib/FixMyStreet/App.pm | 5 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Auth.pm | 3 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/UK.pm | 33 | ||||
-rw-r--r-- | perllib/FixMyStreet/Gaze.pm | 8 | ||||
-rw-r--r-- | t/app/controller/alert.t | 22 | ||||
-rw-r--r-- | templates/web/base/alert/_list.html | 1 | ||||
-rw-r--r-- | templates/web/base/alert/updates.html | 2 | ||||
-rw-r--r-- | templates/web/base/auth/form_extra.html | 0 | ||||
-rw-r--r-- | templates/web/base/report/display_tools.html | 1 | ||||
-rw-r--r-- | templates/web/base/report/form/user_loggedout_by_email.html | 2 | ||||
-rw-r--r-- | templates/web/fixmystreet.com/auth/form_extra.html | 4 |
12 files changed, 84 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b48ffdb0..5c25f3590 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,9 @@ - `#geolocate_link` is now easier to re-style. #3006 - Links inside `#front-main` can be customised using `$primary_link_*` Sass variables. #3007 - Add option to show front end testing code coverage. #3036 + - Add function to fetch user's country from Gaze. + - UK: + - Add option for recaptcha. #3050 * v3.0.1 (6th May 2020) - New features: diff --git a/perllib/FixMyStreet/App.pm b/perllib/FixMyStreet/App.pm index 6a41d93a9..4ca6f23cb 100644 --- a/perllib/FixMyStreet/App.pm +++ b/perllib/FixMyStreet/App.pm @@ -536,6 +536,11 @@ sub check_2fa { return 0; } +sub user_country { + my $c = shift; + return FixMyStreet::Gaze::get_country_from_ip($c->req->address); +} + =head1 SEE ALSO L<FixMyStreet::App::Controller::Root>, L<Catalyst> diff --git a/perllib/FixMyStreet/App/Controller/Auth.pm b/perllib/FixMyStreet/App/Controller/Auth.pm index cecfa318c..beba6b235 100644 --- a/perllib/FixMyStreet/App/Controller/Auth.pm +++ b/perllib/FixMyStreet/App/Controller/Auth.pm @@ -448,6 +448,9 @@ sub check_csrf_token : Private { unless $time && $time > time() - 3600 && $token eq $gen_token; + + # Also check recaptcha if needed + $c->cobrand->call_hook('check_recaptcha'); } sub no_csrf_token : Private { diff --git a/perllib/FixMyStreet/Cobrand/UK.pm b/perllib/FixMyStreet/Cobrand/UK.pm index a42ff58a6..4c62dd538 100644 --- a/perllib/FixMyStreet/Cobrand/UK.pm +++ b/perllib/FixMyStreet/Cobrand/UK.pm @@ -3,6 +3,7 @@ use base 'FixMyStreet::Cobrand::Default'; use strict; use JSON::MaybeXS; +use LWP::UserAgent; use mySociety::MaPit; use mySociety::VotingArea; use Utils; @@ -422,4 +423,36 @@ sub report_new_munge_before_insert { } } +# To use recaptcha, add a RECAPTCHA key to your config, with subkeys secret and +# site_key, taken from the recaptcha site. This shows it to non-UK IP addresses +# on alert and report pages. + +sub requires_recaptcha { + my $self = shift; + my $c = $self->{c}; + + return 0 if $c->user_exists; + return 0 if !FixMyStreet->config('RECAPTCHA'); + return 0 if $c->user_country eq 'GB'; + return 0 unless $c->action =~ /^(alert|report)/; + return 1; +} + +sub check_recaptcha { + my $self = shift; + my $c = $self->{c}; + + return unless $self->requires_recaptcha; + + my $url = 'https://www.google.com/recaptcha/api/siteverify'; + my $res = LWP::UserAgent->new->post($url, { + secret => FixMyStreet->config('RECAPTCHA')->{secret}, + response => $c->get_param('g-recaptcha-response'), + remoteip => $c->req->address, + }); + $res = decode_json($res->content); + $c->detach('/page_error_400_bad_request', ['Bad recaptcha']) + unless $res->{success}; +} + 1; diff --git a/perllib/FixMyStreet/Gaze.pm b/perllib/FixMyStreet/Gaze.pm index bccc81d8c..e2b2e0e08 100644 --- a/perllib/FixMyStreet/Gaze.pm +++ b/perllib/FixMyStreet/Gaze.pm @@ -3,6 +3,7 @@ package FixMyStreet::Gaze; use strict; use warnings; +use FixMyStreet; use mySociety::Gaze; sub get_radius_containing_population ($$) { @@ -24,4 +25,11 @@ sub get_radius_containing_population ($$) { return $dist; } +sub get_country_from_ip { + my ($ip) = @_; + return 'GB' if FixMyStreet->test_mode; + # uncoverable statement + return mySociety::Gaze::get_country_from_ip($ip); +} + 1; diff --git a/t/app/controller/alert.t b/t/app/controller/alert.t index 41aee5bbc..34e68177c 100644 --- a/t/app/controller/alert.t +++ b/t/app/controller/alert.t @@ -1,6 +1,7 @@ use FixMyStreet::TestMech; my $mech = FixMyStreet::TestMech->new; +use Test::MockModule; use t::Mock::Nominatim; # check that we can get the page @@ -73,4 +74,25 @@ FixMyStreet::override_config { is $mech->uri->path, '/rss/reports/Cheltenham/Lansdown'; }; +FixMyStreet::override_config { + ALLOWED_COBRANDS => 'fixmystreet', + MAPIT_URL => 'http://mapit.uk/', + GEOCODER => '', + RECAPTCHA => { secret => 'secret', site_key => 'site_key' }, +}, sub { + subtest 'recaptcha' => sub { + $mech->get_ok('/alert/list?pc=EH11BB'); + $mech->content_lacks('g-recaptcha'); # GB is default test country + + my $mod_app = Test::MockModule->new('FixMyStreet::App'); + $mod_app->mock('user_country', sub { 'FR' }); + my $mod_lwp = Test::MockModule->new('LWP::UserAgent'); + $mod_lwp->mock('post', sub { HTTP::Response->new(200, 'OK', [], '{ "success": true }') }); + + $mech->get_ok('/alert/list?pc=EH11BB'); + $mech->content_contains('g-recaptcha'); + $mech->submit_form_ok({ with_fields => { rznvy => 'someone@example.org' } }); + }; +}; + done_testing(); diff --git a/templates/web/base/alert/_list.html b/templates/web/base/alert/_list.html index 782989a5c..e6c5183e4 100644 --- a/templates/web/base/alert/_list.html +++ b/templates/web/base/alert/_list.html @@ -62,6 +62,7 @@ </div> [% END %] + [% PROCESS 'auth/form_extra.html' %] <div class="alerts__cta-box"> <h3>[% loc('Subscribe by email') %]</h3> diff --git a/templates/web/base/alert/updates.html b/templates/web/base/alert/updates.html index 0fbed2254..40380849f 100644 --- a/templates/web/base/alert/updates.html +++ b/templates/web/base/alert/updates.html @@ -15,6 +15,8 @@ </p> <form action="/alert/subscribe" method="post"> + [% PROCESS 'auth/form_extra.html' %] + <fieldset> [% IF c.user_exists %] [% IF c.user.has_permission_to("contribute_as_another_user", problem.bodies_str_ids) %] diff --git a/templates/web/base/auth/form_extra.html b/templates/web/base/auth/form_extra.html new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/templates/web/base/auth/form_extra.html diff --git a/templates/web/base/report/display_tools.html b/templates/web/base/report/display_tools.html index 4c79e4b71..532c78ec8 100644 --- a/templates/web/base/report/display_tools.html +++ b/templates/web/base/report/display_tools.html @@ -44,6 +44,7 @@ <img src="/i/feed.png" width="16" height="16" title="[% loc('RSS feed') %]" alt="[% loc('RSS feed of updates to this problem' ) %]" border="0"> </a> [% loc('Receive email when updates are left on this problem.' ) %]</p> + [% PROCESS 'auth/form_extra.html' %] <fieldset> [% IF c.user_exists %] [% IF permissions.contribute_as_another_user %] diff --git a/templates/web/base/report/form/user_loggedout_by_email.html b/templates/web/base/report/form/user_loggedout_by_email.html index 33526cc46..459428059 100644 --- a/templates/web/base/report/form/user_loggedout_by_email.html +++ b/templates/web/base/report/form/user_loggedout_by_email.html @@ -62,6 +62,8 @@ <input class="form-control js-password-validate" type="password" name="password_register" id="password_register" aria-describedby="password_register_hint" value=""> + [% PROCESS 'auth/form_extra.html' %] + <input class="btn btn--primary btn--block btn--final js-submit_register" type="submit" name="submit_register" value="[% loc('Submit') %]"> </div> diff --git a/templates/web/fixmystreet.com/auth/form_extra.html b/templates/web/fixmystreet.com/auth/form_extra.html new file mode 100644 index 000000000..8e96b447c --- /dev/null +++ b/templates/web/fixmystreet.com/auth/form_extra.html @@ -0,0 +1,4 @@ +[% IF c.cobrand.requires_recaptcha %] + <script src="https://www.google.com/recaptcha/api.js" async defer></script> + <div class="g-recaptcha" data-sitekey="[% c.config.RECAPTCHA.site_key %]"></div> +[% END %] |