diff options
-rw-r--r-- | CHANGELOG.md | 5 | ||||
-rw-r--r-- | conf/general.yml-example | 3 | ||||
-rw-r--r-- | perllib/FixMyStreet/App.pm | 5 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Auth.pm | 3 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Report/Update.pm | 7 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/UK.pm | 33 | ||||
-rw-r--r-- | perllib/FixMyStreet/Gaze.pm | 8 | ||||
-rw-r--r-- | perllib/FixMyStreet/Script/Alerts.pm | 4 | ||||
-rw-r--r-- | perllib/FixMyStreet/Script/Inactive.pm | 6 | ||||
-rw-r--r-- | t/app/controller/alert.t | 22 | ||||
-rw-r--r-- | t/app/controller/alert_new.t | 2 | ||||
-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 | ||||
-rwxr-xr-x | templates/web/fixmystreet.com/about/privacy.html | 6 | ||||
-rw-r--r-- | templates/web/fixmystreet.com/auth/form_extra.html | 4 | ||||
-rw-r--r-- | templates/web/tfl/front/pre-steps.html | 5 |
19 files changed, 115 insertions, 4 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 733ad04c5..256cf0e5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ * Unreleased - New features: - Add Open Location Codes support to search box. #3047 + - Changes: + - Mark user as active when sent an email alert. - Bugfixes: - Fix issue with dashboard report CSV export. #3026 - bin/update-schema PostgreSQL 12 compatibility. #3043 @@ -16,6 +18,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/conf/general.yml-example b/conf/general.yml-example index 91507b03d..26399bb81 100644 --- a/conf/general.yml-example +++ b/conf/general.yml-example @@ -244,6 +244,9 @@ TESTING_COUNCILS: '' # if you're using Message Manager, include the URL here (see https://github.com/mysociety/message-manager/) MESSAGE_MANAGER_URL: '' +# If you set up using recaptcha, you can put its configuration keys here +RECAPTCHA: '' + # If you want to use SMS login or 'report as' with just a phone number, you'll # need to set the site's two-digit ISO 3166 country code (e.g. GB) here. PHONE_COUNTRY: '' 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/App/Controller/Report/Update.pm b/perllib/FixMyStreet/App/Controller/Report/Update.pm index c5d20a5da..8ffba3dcf 100644 --- a/perllib/FixMyStreet/App/Controller/Report/Update.pm +++ b/perllib/FixMyStreet/App/Controller/Report/Update.pm @@ -484,6 +484,13 @@ sub save_update : Private { $update->confirm(); } elsif ($c->stash->{contributing_as_anonymous_user}) { $update->set_extra_metadata( contributed_as => 'anonymous_user' ); + if ( $c->user_exists && $c->user->from_body ) { + # If a staff user has clicked the 'report anonymously' button then + # there would be no record of who that staff member was as we've + # used the cobrand's anonymous_account for the report. In this case + # record the staff user ID in the report metadata. + $update->set_extra_metadata( contributed_by => $c->user->id ); + } $update->confirm(); } elsif ( !$update->user->in_storage ) { # User does not exist. 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/perllib/FixMyStreet/Script/Alerts.pm b/perllib/FixMyStreet/Script/Alerts.pm index cb1f022fa..d07728092 100644 --- a/perllib/FixMyStreet/Script/Alerts.pm +++ b/perllib/FixMyStreet/Script/Alerts.pm @@ -307,6 +307,10 @@ sub _send_aggregated_alert_email(%) { # Ignore phone-only users return unless $data{alert_user}->email_verified; + # Mark user as active as they're being sent an alert + $data{alert_user}->set_last_active; + $data{alert_user}->update; + my $email = $data{alert_user}->email; my ($domain) = $email =~ m{ @ (.*) \z }x; return if $data{schema}->resultset('Abuse')->search( { diff --git a/perllib/FixMyStreet/Script/Inactive.pm b/perllib/FixMyStreet/Script/Inactive.pm index 8dd524ce1..4d28057d4 100644 --- a/perllib/FixMyStreet/Script/Inactive.pm +++ b/perllib/FixMyStreet/Script/Inactive.pm @@ -158,8 +158,14 @@ sub delete_reports { sub anonymize_users { my $self = shift; + my $body_users = FixMyStreet::DB->resultset("Body")->search({ + comment_user_id => { '!=' => undef }, + }, { + columns => 'comment_user_id', + }); my $users = FixMyStreet::DB->resultset("User")->search({ last_active => { '<', interval($self->anonymize) }, + id => { -not_in => $body_users->as_query }, email => { -not_like => 'removed-%@' . FixMyStreet->config('EMAIL_DOMAIN') }, }); 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/t/app/controller/alert_new.t b/t/app/controller/alert_new.t index 7eba90530..d968b56b1 100644 --- a/t/app/controller/alert_new.t +++ b/t/app/controller/alert_new.t @@ -523,6 +523,8 @@ subtest "Test alerts are not sent for no-text updates" => sub { }; $mech->email_count_is(1); + $user2->discard_changes; + isnt $user2->last_active, undef, 'Last active has been set'; $mech->delete_user($user1); $mech->delete_user($user2); 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/about/privacy.html b/templates/web/fixmystreet.com/about/privacy.html index 8ed953cc9..665b0968b 100755 --- a/templates/web/fixmystreet.com/about/privacy.html +++ b/templates/web/fixmystreet.com/about/privacy.html @@ -287,8 +287,10 @@ When you make a report </p> <p> + Personal details will automatically be removed from our database after two + years of inactivity of the associated account. Please <a href="/contact">contact us</a> if you would like your details to be removed from our admin - database. + database sooner than that. </p> <h3> @@ -297,7 +299,7 @@ When you make a report <p> If you contact FixMyStreet via our support email address we keep your message for two - years at which point they will be automatically deleted.. This is to aid continuity + years at which point it will be automatically deleted. This is to aid continuity and so that we can view any historic context which may have bearing on subsequent support mail, even if members of the support staff change. Support staff adhere to internal privacy policies which may be viewed on request. 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..92cc31050 --- /dev/null +++ b/templates/web/fixmystreet.com/auth/form_extra.html @@ -0,0 +1,4 @@ +[% IF c.cobrand.requires_recaptcha %] + <script nonce="[% csp_nonce %]" src="https://www.google.com/recaptcha/api.js" async defer></script> + <div class="g-recaptcha" data-sitekey="[% c.config.RECAPTCHA.site_key %]"></div> +[% END %] diff --git a/templates/web/tfl/front/pre-steps.html b/templates/web/tfl/front/pre-steps.html index ee22f4978..1dead5c89 100644 --- a/templates/web/tfl/front/pre-steps.html +++ b/templates/web/tfl/front/pre-steps.html @@ -6,6 +6,7 @@ safety critical issues. </strong> <br> - We will continue to serve you the best that we can but urge everyone not to - make journeys unless absolutely necessary. + If you are concerned about pavement overcrowding during social distancing + on the Transport for London Road Network, you can now report that to us + here. </p> |