aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--perllib/FixMyStreet/App/Controller/Admin.pm77
-rw-r--r--perllib/FixMyStreet/App/Controller/Alert.pm6
-rw-r--r--perllib/FixMyStreet/App/Controller/Around.pm2
-rw-r--r--perllib/FixMyStreet/App/Controller/Auth.pm113
-rw-r--r--perllib/FixMyStreet/App/Controller/Moderate.pm2
-rw-r--r--perllib/FixMyStreet/App/Controller/Report.pm3
-rw-r--r--perllib/FixMyStreet/App/Controller/Report/New.pm2
-rw-r--r--perllib/FixMyStreet/App/Controller/Report/Update.pm1
-rw-r--r--perllib/FixMyStreet/Cobrand/Zurich.pm6
-rw-r--r--perllib/FixMyStreet/DB/Result/User.pm27
-rw-r--r--t/app/controller/alert_new.t12
-rw-r--r--t/app/controller/auth.t56
-rw-r--r--t/app/controller/moderate.t76
-rw-r--r--t/app/controller/photo.t7
-rw-r--r--t/app/controller/report_updates.t80
-rw-r--r--t/cobrand/zurich.t11
-rw-r--r--templates/email/bromley/questionnaire.txt10
-rw-r--r--templates/email/default/change_email.txt11
-rw-r--r--templates/web/base/admin/body-form.html2
-rw-r--r--templates/web/base/admin/body.html4
-rw-r--r--templates/web/base/admin/category_edit.html2
-rw-r--r--templates/web/base/admin/report_edit.html2
-rw-r--r--templates/web/base/admin/update_edit.html2
-rw-r--r--templates/web/base/admin/user-form.html2
-rw-r--r--templates/web/base/alert/_list.html1
-rw-r--r--templates/web/base/alert/updates.html1
-rwxr-xr-xtemplates/web/base/around/display_location.html1
-rw-r--r--templates/web/base/auth/change_email.html37
-rw-r--r--templates/web/base/auth/change_password.html7
-rw-r--r--templates/web/base/auth/general.html11
-rw-r--r--templates/web/base/my/my.html1
-rw-r--r--templates/web/base/report/_main.html1
-rw-r--r--templates/web/base/report/display_tools.html2
-rw-r--r--templates/web/base/report/new/fill_in_details.html5
-rw-r--r--templates/web/base/report/update-form.html1
-rw-r--r--templates/web/base/report/update.html1
-rw-r--r--templates/web/bromley/report/display.html1
-rw-r--r--templates/web/eastsussex/report/update-form.html2
-rw-r--r--templates/web/seesomething/around/display_location.html1
-rw-r--r--templates/web/zurich/admin/body-form.html2
-rw-r--r--templates/web/zurich/admin/body.html2
-rw-r--r--templates/web/zurich/admin/report_edit-sdm.html2
-rw-r--r--templates/web/zurich/admin/report_edit.html2
-rw-r--r--templates/web/zurich/admin/template_edit.html2
-rw-r--r--templates/web/zurich/admin/update_edit.html2
45 files changed, 376 insertions, 225 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm
index 4e288556f..e68eb00a5 100644
--- a/perllib/FixMyStreet/App/Controller/Admin.pm
+++ b/perllib/FixMyStreet/App/Controller/Admin.pm
@@ -215,7 +215,7 @@ sub bodies : Path('bodies') : Args(0) {
return;
}
- $c->forward( 'get_token' );
+ $c->forward( '/auth/get_csrf_token' );
my $edit_activity = $c->model('DB::ContactsHistory')->search(
undef,
@@ -232,7 +232,7 @@ sub bodies : Path('bodies') : Args(0) {
my $posted = $c->get_param('posted') || '';
if ( $posted eq 'body' ) {
$c->forward('check_for_super_user');
- $c->forward('check_token');
+ $c->forward('/auth/check_csrf_token');
my $params = $c->forward('body_params');
my $body = $c->model('DB::Body')->create( $params );
@@ -289,7 +289,7 @@ sub body : Path('body') : Args(1) {
$c->stash->{body_id} = $body_id;
$c->forward( 'check_for_super_user' );
- $c->forward( 'get_token' );
+ $c->forward( '/auth/get_csrf_token' );
$c->forward( 'lookup_body' );
$c->forward( 'fetch_all_bodies' );
$c->forward( 'body_form_dropdowns' );
@@ -318,7 +318,7 @@ sub update_contacts : Private {
my $editor = $c->forward('get_user');
if ( $posted eq 'new' ) {
- $c->forward('check_token');
+ $c->forward('/auth/check_csrf_token');
my %errors;
@@ -370,7 +370,7 @@ sub update_contacts : Private {
}
} elsif ( $posted eq 'update' ) {
- $c->forward('check_token');
+ $c->forward('/auth/check_csrf_token');
my @categories = $c->get_param_list('confirmed');
@@ -393,7 +393,7 @@ sub update_contacts : Private {
$c->stash->{updated} = _('Values updated');
} elsif ( $posted eq 'body' ) {
$c->forward('check_for_super_user');
- $c->forward('check_token');
+ $c->forward('/auth/check_csrf_token');
my $params = $c->forward( 'body_params' );
$c->stash->{body}->update( $params );
@@ -476,7 +476,7 @@ sub category_edit : Path('body') : Args(2) {
$c->stash->{body_id} = $body_id;
- $c->forward( 'get_token' );
+ $c->forward( '/auth/get_csrf_token' );
$c->forward( 'lookup_body' );
my $contact = $c->stash->{body}->contacts->search( { category => $category } )->first;
@@ -643,7 +643,7 @@ sub report_edit : Path('report_edit') : Args(1) {
$c->stash->{problem} = $problem;
- $c->forward('get_token');
+ $c->forward('/auth/get_csrf_token');
if ( $c->cobrand->moniker eq 'zurich' ) {
$c->stash->{page} = 'admin';
@@ -689,7 +689,7 @@ sub report_edit : Path('report_edit') : Args(1) {
->all ];
if ( $c->get_param('resend') ) {
- $c->forward('check_token');
+ $c->forward('/auth/check_csrf_token');
$problem->whensent(undef);
$problem->update();
@@ -699,7 +699,7 @@ sub report_edit : Path('report_edit') : Args(1) {
$c->forward( 'log_edit', [ $id, 'problem', 'resend' ] );
}
elsif ( $c->get_param('mark_sent') ) {
- $c->forward('check_token');
+ $c->forward('/auth/check_csrf_token');
$problem->whensent(\'current_timestamp');
$problem->update();
$c->stash->{status_message} = '<p><em>' . _('That problem has been marked as sent.') . '</em></p>';
@@ -717,7 +717,7 @@ sub report_edit : Path('report_edit') : Args(1) {
$c->forward('ban_user');
}
elsif ( $c->get_param('submit') ) {
- $c->forward('check_token');
+ $c->forward('/auth/check_csrf_token');
my $done = 0;
my $edited = 0;
@@ -917,7 +917,7 @@ sub users: Path('users') : Args(0) {
}
} else {
- $c->forward('get_token');
+ $c->forward('/auth/get_csrf_token');
$c->forward('fetch_all_bodies');
# Admin users by default
@@ -942,7 +942,7 @@ sub update_edit : Path('update_edit') : Args(1) {
$c->detach( '/page_error_404_not_found' )
unless $update;
- $c->forward('get_token');
+ $c->forward('/auth/get_csrf_token');
$c->stash->{update} = $update;
@@ -965,7 +965,7 @@ sub update_edit : Path('update_edit') : Args(1) {
$c->stash->{update}->discard_changes;
}
elsif ( $c->get_param('submit') ) {
- $c->forward('check_token');
+ $c->forward('/auth/check_csrf_token');
my $old_state = $update->state;
my $new_state = $c->get_param('state');
@@ -1047,12 +1047,12 @@ sub user_add : Path('user_edit') : Args(0) {
my ( $self, $c ) = @_;
$c->stash->{template} = 'admin/user_edit.html';
- $c->forward('get_token');
+ $c->forward('/auth/get_csrf_token');
$c->forward('fetch_all_bodies');
return unless $c->get_param('submit');
- $c->forward('check_token');
+ $c->forward('/auth/check_csrf_token');
unless ($c->get_param('email')) {
$c->stash->{field_errors}->{email} = _('Please enter a valid email');
@@ -1084,7 +1084,7 @@ sub user_add : Path('user_edit') : Args(0) {
sub user_edit : Path('user_edit') : Args(1) {
my ( $self, $c, $id ) = @_;
- $c->forward('get_token');
+ $c->forward('/auth/get_csrf_token');
my $user = $c->model('DB::User')->find( { id => $id } );
$c->stash->{user} = $user;
@@ -1092,7 +1092,7 @@ sub user_edit : Path('user_edit') : Args(1) {
$c->forward('fetch_all_bodies');
if ( $c->get_param('submit') ) {
- $c->forward('check_token');
+ $c->forward('/auth/check_csrf_token');
my $edited = 0;
@@ -1120,12 +1120,7 @@ sub user_edit : Path('user_edit') : Args(1) {
my $existing_user = $c->model('DB::User')->search({ email => $user->email, id => { '!=', $user->id } })->first;
if ($existing_user) {
- foreach (qw(Problem Comment Alert)) {
- $c->model("DB::$_")
- ->search({ user_id => $user->id })
- ->update({ user_id => $existing_user->id });
- }
- $user->delete;
+ $existing_user->adopt($user);
$c->forward( 'log_edit', [ $id, 'user', 'merge' ] );
$c->res->redirect( $c->uri_for( 'user_edit', $existing_user->id ) );
} else {
@@ -1328,40 +1323,6 @@ sub get_user : Private {
return $user;
}
-=item get_token
-
-Generate a token based on user and secret
-
-=cut
-
-sub get_token : Private {
- my ( $self, $c ) = @_;
-
- my $secret = $c->model('DB::Secret')->get;
- my $user = $c->forward('get_user');
- my $token = sha1_hex($user . $secret);
- $c->stash->{token} = $token;
-
- return 1;
-}
-
-=item check_token
-
-Check that a token has been set on a request and it's the correct token. If
-not then display 404 page
-
-=cut
-
-sub check_token : Private {
- my ( $self, $c ) = @_;
-
- if ( !$c->get_param('token') || $c->get_param('token') ne $c->stash->{token} ) {
- $c->detach( '/page_error_404_not_found' );
- }
-
- return 1;
-}
-
=item log_edit
$c->forward( 'log_edit', [ $object_id, $object_type, $action_performed ] );
diff --git a/perllib/FixMyStreet/App/Controller/Alert.pm b/perllib/FixMyStreet/App/Controller/Alert.pm
index ddda02abd..b578fbbcc 100644
--- a/perllib/FixMyStreet/App/Controller/Alert.pm
+++ b/perllib/FixMyStreet/App/Controller/Alert.pm
@@ -36,6 +36,8 @@ sub index : Path('') : Args(0) {
sub list : Path('list') : Args(0) {
my ( $self, $c ) = @_;
+ $c->forward('/auth/get_csrf_token');
+
return
unless $c->forward('setup_request')
&& $c->forward('prettify_pc')
@@ -112,6 +114,8 @@ Sign up to email alerts
sub subscribe_email : Private {
my ( $self, $c ) = @_;
+ $c->forward('/auth/check_csrf_token');
+
$c->stash->{errors} = [];
$c->forward('process_user');
@@ -146,6 +150,8 @@ sub subscribe_email : Private {
sub updates : Path('updates') : Args(0) {
my ( $self, $c ) = @_;
+ $c->forward('/auth/get_csrf_token');
+
$c->stash->{email} = $c->get_param('rznvy');
$c->stash->{problem_id} = $c->get_param('id');
}
diff --git a/perllib/FixMyStreet/App/Controller/Around.pm b/perllib/FixMyStreet/App/Controller/Around.pm
index b0340204a..b8f038ce3 100644
--- a/perllib/FixMyStreet/App/Controller/Around.pm
+++ b/perllib/FixMyStreet/App/Controller/Around.pm
@@ -156,6 +156,8 @@ sub display_location : Private {
# set the template to use
$c->stash->{template} = 'around/display_location.html';
+ $c->forward('/auth/get_csrf_token');
+
# get the lat,lng
my $latitude = $c->stash->{latitude};
my $longitude = $c->stash->{longitude};
diff --git a/perllib/FixMyStreet/App/Controller/Auth.pm b/perllib/FixMyStreet/App/Controller/Auth.pm
index c5a6cf9bf..b564a988c 100644
--- a/perllib/FixMyStreet/App/Controller/Auth.pm
+++ b/perllib/FixMyStreet/App/Controller/Auth.pm
@@ -6,8 +6,9 @@ BEGIN { extends 'Catalyst::Controller'; }
use Email::Valid;
use Net::Domain::TLD;
-use mySociety::AuthToken;
+use Digest::HMAC_SHA1 qw(hmac_sha1);
use JSON::MaybeXS;
+use MIME::Base64;
use Net::Facebook::Oauth2;
use Net::Twitter::Lite::WithAPIv1_1;
@@ -37,16 +38,17 @@ sub general : Path : Args(0) {
# all done unless we have a form posted to us
return unless $c->req->method eq 'POST';
- # decide which action to take
- $c->detach('facebook_sign_in') if $c->get_param('facebook_sign_in');
- $c->detach('twitter_sign_in') if $c->get_param('twitter_sign_in');
-
- my $clicked_password = $c->get_param('sign_in');
my $clicked_email = $c->get_param('email_sign_in');
+ my $data_address = $c->get_param('email');
my $data_password = $c->get_param('password_sign_in');
my $data_email = $c->get_param('name') || $c->get_param('password_register');
+ # decide which action to take
$c->detach('email_sign_in') if $clicked_email || ($data_email && !$data_password);
+ if (!$data_address && !$data_password && !$data_email) {
+ $c->detach('facebook_sign_in') if $c->get_param('facebook_sign_in');
+ $c->detach('twitter_sign_in') if $c->get_param('twitter_sign_in');
+ }
$c->forward( 'sign_in' )
&& $c->detach( 'redirect_on_signin', [ $c->get_param('r') ] );
@@ -137,6 +139,10 @@ sub email_sign_in : Private {
if $c->get_param('oauth_need_email') && $c->session->{oauth}{facebook_id};
$token_data->{twitter_id} = $c->session->{oauth}{twitter_id}
if $c->get_param('oauth_need_email') && $c->session->{oauth}{twitter_id};
+ if ($c->stash->{current_user}) {
+ $token_data->{old_email} = $c->stash->{current_user}->email;
+ $token_data->{r} = 'auth/change_email/success';
+ }
my $token_obj = $c->model('DB::Token')->create({
scope => 'email_sign_in',
@@ -144,7 +150,8 @@ sub email_sign_in : Private {
});
$c->stash->{token} = $token_obj->token;
- $c->send_email( 'login.txt', { to => $good_email } );
+ my $template = $c->stash->{email_template} || 'login.txt';
+ $c->send_email( $template, { to => $good_email } );
$c->stash->{template} = 'auth/token.html';
}
@@ -175,17 +182,40 @@ sub token : Path('/M') : Args(1) {
return;
}
- # Sign out in case we are another user
- $c->logout();
-
# find or create the user related to the token.
my $data = $token_obj->data;
- my $user = $c->model('DB::User')->find_or_create( { email => $data->{email} } );
+
+ if ($data->{old_email} && (!$c->user_exists || $c->user->email ne $data->{old_email})) {
+ $c->stash->{token_not_found} = 1;
+ return;
+ }
+
+ # sign out in case we are another user
+ $c->logout();
+
+ my $user = $c->model('DB::User')->find_or_new({ email => $data->{email} });
+
+ if ($data->{old_email}) {
+ # Were logged in as old_email, want to switch to email ($user)
+ if ($user->in_storage) {
+ my $old_user = $c->model('DB::User')->find({ email => $data->{old_email} });
+ if ($old_user) {
+ $old_user->adopt($user);
+ $user = $old_user;
+ $user->email($data->{email});
+ }
+ } else {
+ # Updating to a new (to the db) email address, easier!
+ $user = $c->model('DB::User')->find({ email => $data->{old_email} });
+ $user->email($data->{email});
+ }
+ }
+
$user->name( $data->{name} ) if $data->{name};
$user->password( $data->{password}, 1 ) if $data->{password};
$user->facebook_id( $data->{facebook_id} ) if $data->{facebook_id};
$user->twitter_id( $data->{twitter_id} ) if $data->{twitter_id};
- $user->update;
+ $user->update_or_insert;
$c->authenticate( { email => $user->email }, 'no_password' );
# send the user to their page
@@ -414,12 +444,13 @@ sub change_password : Local {
$c->detach( 'redirect' ) unless $c->user;
- # FIXME - CSRF check here
- # FIXME - minimum criteria for passwords (length, contain number, etc)
+ $c->forward('get_csrf_token');
# If not a post then no submission
return unless $c->req->method eq 'POST';
+ $c->forward('check_csrf_token');
+
# get the passwords
my $new = $c->get_param('new_password') // '';
my $confirm = $c->get_param('confirm') // '';
@@ -443,6 +474,60 @@ sub change_password : Local {
}
+=head2 change_email
+
+Let the user change their email.
+
+=cut
+
+sub change_email : Local {
+ my ( $self, $c ) = @_;
+
+ $c->detach( 'redirect' ) unless $c->user;
+
+ $c->forward('get_csrf_token');
+
+ # If not a post then no submission
+ return unless $c->req->method eq 'POST';
+
+ $c->forward('check_csrf_token');
+ $c->stash->{current_user} = $c->user;
+ $c->stash->{email_template} = 'change_email.txt';
+ $c->forward('email_sign_in');
+}
+
+sub get_csrf_token : Private {
+ my ( $self, $c ) = @_;
+
+ my $time = $c->stash->{csrf_time} || time();
+ my $hash = hmac_sha1("$time-" . ($c->sessionid || ""), $c->model('DB::Secret')->get);
+ $hash = encode_base64($hash, "");
+ $hash =~ s/=$//;
+ my $token = "$time-$hash";
+ $c->stash->{csrf_token} = $token unless $c->stash->{csrf_time};
+ return $token;
+}
+
+sub check_csrf_token : Private {
+ my ( $self, $c ) = @_;
+
+ my $token = $c->get_param('token') || "";
+ $token =~ s/ /+/g;
+ my ($time) = $token =~ /^(\d+)-[0-9a-zA-Z+\/]+$/;
+ $c->stash->{csrf_time} = $time;
+ $c->detach('no_csrf_token')
+ unless $time
+ && $time > time() - 3600
+ && $token eq $c->forward('get_csrf_token');
+ delete $c->stash->{csrf_time};
+}
+
+sub no_csrf_token : Private {
+ my ($self, $c) = @_;
+ $c->stash->{message} = _('Unknown error');
+ $c->stash->{template} = 'errors/generic.html';
+}
+
=head2 sign_out
Log the user out. Tell them we've done so.
diff --git a/perllib/FixMyStreet/App/Controller/Moderate.pm b/perllib/FixMyStreet/App/Controller/Moderate.pm
index 77a3346dc..2d23417b9 100644
--- a/perllib/FixMyStreet/App/Controller/Moderate.pm
+++ b/perllib/FixMyStreet/App/Controller/Moderate.pm
@@ -57,6 +57,8 @@ sub report : Chained('moderate') : PathPart('report') : CaptureArgs(1) {
$c->detach unless $c->user_exists;
$c->detach unless $c->user->has_permission_to(moderate => $problem->bodies_str);
+ $c->forward('/auth/check_csrf_token');
+
my $original = $problem->find_or_new_related( moderation_original_data => {
title => $problem->title,
detail => $problem->detail,
diff --git a/perllib/FixMyStreet/App/Controller/Report.pm b/perllib/FixMyStreet/App/Controller/Report.pm
index b3e546c2c..89df4a52d 100644
--- a/perllib/FixMyStreet/App/Controller/Report.pm
+++ b/perllib/FixMyStreet/App/Controller/Report.pm
@@ -72,6 +72,7 @@ sub ajax : Path('ajax') : Args(1) {
sub _display : Private {
my ( $self, $c, $id ) = @_;
+ $c->forward('/auth/get_csrf_token');
$c->forward( 'load_problem_or_display_error', [ $id ] );
$c->forward( 'load_updates' );
$c->forward( 'format_problem_for_display' );
@@ -249,6 +250,8 @@ users too about this change, at which point we can delete:
sub delete :Local :Args(1) {
my ( $self, $c, $id ) = @_;
+ $c->forward('/auth/check_csrf_token');
+
$c->forward( 'load_problem_or_display_error', [ $id ] );
my $p = $c->stash->{problem};
diff --git a/perllib/FixMyStreet/App/Controller/Report/New.pm b/perllib/FixMyStreet/App/Controller/Report/New.pm
index af9ca50b5..9779a5e2a 100644
--- a/perllib/FixMyStreet/App/Controller/Report/New.pm
+++ b/perllib/FixMyStreet/App/Controller/Report/New.pm
@@ -81,6 +81,7 @@ sub report_new : Path : Args(0) {
# create the report - loading a partial if available
$c->forward('initialize_report');
+ $c->forward('/auth/get_csrf_token');
# work out the location for this report and do some checks
# Also show map if we're just updating the filters
@@ -96,6 +97,7 @@ sub report_new : Path : Args(0) {
# deal with the user and report and check both are happy
return unless $c->forward('check_form_submitted');
+ $c->forward('/auth/check_csrf_token');
$c->forward('process_user');
$c->forward('process_report');
$c->forward('/photo/process_photo');
diff --git a/perllib/FixMyStreet/App/Controller/Report/Update.pm b/perllib/FixMyStreet/App/Controller/Report/Update.pm
index 275a300bd..d03797f56 100644
--- a/perllib/FixMyStreet/App/Controller/Report/Update.pm
+++ b/perllib/FixMyStreet/App/Controller/Report/Update.pm
@@ -25,6 +25,7 @@ sub report_update : Path : Args(0) {
$c->forward('check_form_submitted')
or $c->go( '/report/display', [ $c->stash->{problem}->id ] );
+ $c->forward('/auth/check_csrf_token');
$c->forward('process_update');
$c->forward('process_user');
$c->forward('/photo/process_photo');
diff --git a/perllib/FixMyStreet/Cobrand/Zurich.pm b/perllib/FixMyStreet/Cobrand/Zurich.pm
index 987f0bb67..2e4a167db 100644
--- a/perllib/FixMyStreet/Cobrand/Zurich.pm
+++ b/perllib/FixMyStreet/Cobrand/Zurich.pm
@@ -541,7 +541,7 @@ sub admin_report_edit {
# If super or dm check that the token is correct before proceeding
if ( ($type eq 'super' || $type eq 'dm') && $c->get_param('submit') ) {
- $c->forward('check_token');
+ $c->forward('/auth/check_csrf_token');
}
# All types of users can add internal notes
@@ -807,7 +807,7 @@ sub admin_report_edit {
# subdivision, or because the customer was not contactable.
# We handle these in the same way but with different statuses.
- $c->forward('check_token');
+ $c->forward('/auth/check_csrf_token');
my $not_contactable = $c->get_param('not_contactable');
@@ -829,7 +829,7 @@ sub admin_report_edit {
$self->update_admin_log($c, $problem);
$c->res->redirect( '/admin/summary' );
} elsif ($c->get_param('submit')) {
- $c->forward('check_token');
+ $c->forward('/auth/check_csrf_token');
my $db_update = 0;
if ( $c->get_param('latitude') != $problem->latitude || $c->get_param('longitude') != $problem->longitude ) {
diff --git a/perllib/FixMyStreet/DB/Result/User.pm b/perllib/FixMyStreet/DB/Result/User.pm
index 054be3644..7356969d1 100644
--- a/perllib/FixMyStreet/DB/Result/User.pm
+++ b/perllib/FixMyStreet/DB/Result/User.pm
@@ -239,9 +239,30 @@ sub has_permission_to {
return $permission ? 1 : undef;
}
-sub print {
- my $self = shift;
- return '[' . (join '-', @_) . ']';
+sub adopt {
+ my ($self, $other) = @_;
+
+ return if $self->id == $other->id;
+
+ # Move most things from $other to $self
+ foreach (qw(Problem Comment Alert AdminLog )) {
+ $self->result_source->schema->resultset($_)
+ ->search({ user_id => $other->id })
+ ->update({ user_id => $self->id });
+ }
+
+ # It's possible the user permissions for the other user exist, so
+ # try updating, and then delete anyway.
+ foreach ($self->result_source->schema->resultset("UserBodyPermission")
+ ->search({ user_id => $other->id })->all) {
+ eval {
+ $_->update({ user_id => $self->id });
+ };
+ $_->delete if $@;
+ }
+
+ # Delete the now empty user
+ $other->delete;
}
1;
diff --git a/t/app/controller/alert_new.t b/t/app/controller/alert_new.t
index 777d733e2..06932f70a 100644
--- a/t/app/controller/alert_new.t
+++ b/t/app/controller/alert_new.t
@@ -7,6 +7,10 @@ use FixMyStreet::App;
my $mech = FixMyStreet::TestMech->new;
+$mech->log_in_ok('test@example.com');
+$mech->get_ok('/alert/subscribe?id=1');
+my ($csrf) = $mech->content =~ /name="token" value="([^"]*)"/;
+
foreach my $test (
{
email => 'test@example.com',
@@ -71,7 +75,7 @@ foreach my $test (
$mech->delete_user($user);
}
- $mech->get_ok( $test->{uri} );
+ $mech->get_ok( $test->{uri} . "&token=$csrf" );
$mech->content_contains( $test->{content} );
$user =
@@ -113,7 +117,7 @@ foreach my $test (
my $existing_id = $alert->id;
my $existing_token = $url_token;
- $mech->get_ok( $test->{uri} );
+ $mech->get_ok( $test->{uri} . "&token=$csrf" );
$email = $mech->get_email;
ok $email, 'got a second email';
@@ -165,7 +169,7 @@ foreach my $test (
# clear existing data so we can be sure we're creating it
ok $alert->delete() if $alert && !$test->{exist};
- $mech->get_ok( '/alert/subscribe?type=local&rznvy=test-new@example.com&feed=area:1000:A_Location' );
+ $mech->get_ok( '/alert/subscribe?type=local&rznvy=test-new@example.com&feed=area:1000:A_Location&token=' . $csrf );
$alert = FixMyStreet::App->model('DB::Alert')->find(
{
@@ -262,7 +266,7 @@ for my $test (
FixMyStreet::App->model('DB::Abuse')
->find_or_create( { email => $test->{email} } );
- $mech->get_ok( $test->{uri} );
+ $mech->get_ok( $test->{uri} . "&token=$csrf" );
$mech->content_contains( $test->{content} );
$user =
diff --git a/t/app/controller/auth.t b/t/app/controller/auth.t
index 235a3af7e..60f22acfb 100644
--- a/t/app/controller/auth.t
+++ b/t/app/controller/auth.t
@@ -7,11 +7,13 @@ use FixMyStreet::TestMech;
my $mech = FixMyStreet::TestMech->new;
my $test_email = 'test@example.com';
+my $test_email2 = 'test@example.net';
my $test_password = 'foobar';
$mech->delete_user($test_email);
END {
$mech->delete_user($test_email);
+ $mech->delete_user($test_email2);
done_testing();
}
@@ -63,7 +65,6 @@ $mech->not_logged_in_ok;
# check that we got one email
{
- $mech->email_count_is(1);
my $email = $mech->get_email;
$mech->clear_emails_ok;
is $email->header('Subject'), "Your FixMyStreet account details",
@@ -116,7 +117,6 @@ $mech->not_logged_in_ok;
# follow link and change password - check not prompted for old password
$mech->not_logged_in_ok;
- $mech->email_count_is(1);
my $email = $mech->get_email;
$mech->clear_emails_ok;
my ($link) = $email->body =~ m{(http://\S+)};
@@ -128,7 +128,7 @@ $mech->not_logged_in_ok;
ok my $form = $mech->form_name('change_password'),
"found change password form";
is_deeply [ sort grep { $_ } map { $_->name } $form->inputs ], #
- [ 'confirm', 'new_password' ],
+ [ 'confirm', 'new_password', 'token' ],
"check we got expected fields (ie not old_password)";
# check the various ways the form can be wrong
@@ -175,6 +175,54 @@ $mech->not_logged_in_ok;
ok $user->password, "user now has a password";
}
+subtest "Test change email page" => sub {
+ # Still signed in from the above test
+ $mech->get_ok('/my');
+ $mech->follow_link_ok({url => '/auth/change_email'});
+ $mech->submit_form_ok(
+ { with_fields => { email => "" } },
+ "submit blank change email form"
+ );
+ $mech->content_contains( 'Please enter your email', "found expected error" );
+ $mech->submit_form_ok({ with_fields => { email => $test_email2 } }, "change_email to $test_email2");
+ is $mech->uri->path, '/auth/change_email', "still on change email page";
+ $mech->content_contains( 'Now check your email', "found check your email" );
+ my $email = $mech->get_email;
+ $mech->clear_emails_ok;
+ my ($link) = $email->body =~ m{(http://\S+)};
+ $mech->get_ok($link);
+ is $mech->uri->path, '/auth/change_email/success', "redirected to the change_email page";
+ $mech->content_contains('successfully confirmed');
+ ok(FixMyStreet::App->model('DB::User')->find( { email => $test_email2 } ), "got a user");
+
+ ok(FixMyStreet::App->model('DB::User')->create( { email => $test_email } ), "created old user");
+ $mech->submit_form_ok({ with_fields => { email => $test_email } },
+ "change_email back to $test_email"
+ );
+ is $mech->uri->path, '/auth/change_email', "still on change email page";
+ $mech->content_contains( 'Now check your email', "found check your email" );
+ $email = $mech->get_email;
+ $mech->clear_emails_ok;
+ ($link) = $email->body =~ m{(http://\S+)};
+ $mech->get_ok($link);
+ is $mech->uri->path, '/auth/change_email/success', "redirected to the change_email page";
+ $mech->content_contains('successfully confirmed');
+
+ # Test you can't click the link if logged out
+ $mech->submit_form_ok({ with_fields => { email => $test_email } },
+ "change_email back to $test_email"
+ );
+ is $mech->uri->path, '/auth/change_email', "still on change email page";
+ $mech->content_contains( 'Now check your email', "found check your email" );
+ $email = $mech->get_email;
+ $mech->clear_emails_ok;
+ ($link) = $email->body =~ m{(http://\S+)};
+ $mech->log_out_ok;
+ $mech->get_ok($link);
+ isnt $mech->uri->path, '/auth/change_email/success', "not redirected to the change_email page";
+ $mech->content_contains('Sorry');
+};
+
foreach my $remember_me ( '1', '0' ) {
subtest "sign in using valid details (remember_me => '$remember_me')" => sub {
$mech->get_ok('/auth');
@@ -188,7 +236,7 @@ foreach my $remember_me ( '1', '0' ) {
},
button => 'sign_in',
},
- "sign in with '$test_email' & '$test_password"
+ "sign in with '$test_email' & '$test_password'"
);
is $mech->uri->path, '/my', "redirected to correct page";
diff --git a/t/app/controller/moderate.t b/t/app/controller/moderate.t
index b79f50e73..38216c708 100644
--- a/t/app/controller/moderate.t
+++ b/t/app/controller/moderate.t
@@ -8,6 +8,7 @@ use FixMyStreet::App;
use Data::Dumper;
my $mech = FixMyStreet::TestMech->new;
+$mech->host('www.example.org');
my $BROMLEY_ID = 2482;
my $body = $mech->create_body_ok( $BROMLEY_ID, 'Bromley Council' );
@@ -92,11 +93,12 @@ my %problem_prepopulated = (
subtest 'Problem moderation' => sub {
subtest 'Post modify title and text' => sub {
- $mech->post_ok('/moderate/report/' . $report->id, {
+ $mech->get_ok($REPORT_URL);
+ $mech->submit_form_ok({ with_fields => {
%problem_prepopulated,
problem_title => 'Good good',
problem_detail => 'Good good improved',
- });
+ }});
$mech->base_like( qr{\Q$REPORT_URL\E} );
$report->discard_changes;
@@ -105,11 +107,11 @@ subtest 'Problem moderation' => sub {
};
subtest 'Revert title and text' => sub {
- $mech->post_ok('/moderate/report/' . $report->id, {
+ $mech->submit_form_ok({ with_fields => {
%problem_prepopulated,
problem_revert_title => 1,
problem_revert_detail => 1,
- });
+ }});
$mech->base_like( qr{\Q$REPORT_URL\E} );
$report->discard_changes;
@@ -120,18 +122,18 @@ subtest 'Problem moderation' => sub {
subtest 'Make anonymous' => sub {
$mech->content_lacks('Reported anonymously');
- $mech->post_ok('/moderate/report/' . $report->id, {
+ $mech->submit_form_ok({ with_fields => {
%problem_prepopulated,
problem_show_name => 0,
- });
+ }});
$mech->base_like( qr{\Q$REPORT_URL\E} );
$mech->content_contains('Reported anonymously');
- $mech->post_ok('/moderate/report/' . $report->id, {
+ $mech->submit_form_ok({ with_fields => {
%problem_prepopulated,
problem_show_name => 1,
- });
+ }});
$mech->base_like( qr{\Q$REPORT_URL\E} );
$mech->content_lacks('Reported anonymously');
@@ -140,18 +142,18 @@ subtest 'Problem moderation' => sub {
subtest 'Hide photo' => sub {
$mech->content_contains('Photo of this report');
- $mech->post_ok('/moderate/report/' . $report->id, {
+ $mech->submit_form_ok({ with_fields => {
%problem_prepopulated,
problem_show_photo => 0,
- });
+ }});
$mech->base_like( qr{\Q$REPORT_URL\E} );
$mech->content_lacks('Photo of this report');
- $mech->post_ok('/moderate/report/' . $report->id, {
+ $mech->submit_form_ok({ with_fields => {
%problem_prepopulated,
problem_show_photo => 1,
- });
+ }});
$mech->base_like( qr{\Q$REPORT_URL\E} );
$mech->content_contains('Photo of this report');
@@ -160,10 +162,10 @@ subtest 'Problem moderation' => sub {
subtest 'Hide report' => sub {
$mech->clear_emails_ok;
- my $resp = $mech->post('/moderate/report/' . $report->id, {
+ $mech->submit_form_ok({ with_fields => {
%problem_prepopulated,
problem_hide => 1,
- });
+ }});
$mech->base_unlike( qr{/report/}, 'redirected to front page' );
$report->discard_changes;
@@ -185,22 +187,23 @@ $mech->content_lacks('Posted anonymously', 'sanity check');
subtest 'Problem 2' => sub {
my $REPORT2_URL = '/report/' . $report2->id ;
- $mech->post_ok('/moderate/report/' . $report2->id, {
+ $mech->get_ok($REPORT2_URL);
+ $mech->submit_form_ok({ with_fields => {
%problem_prepopulated,
problem_title => 'Good good',
problem_detail => 'Good good improved',
- });
+ }});
$mech->base_like( qr{\Q$REPORT2_URL\E} );
$report2->discard_changes;
is $report2->title, 'Good [...] good';
is $report2->detail, 'Good [...] good [...]improved';
- $mech->post_ok('/moderate/report/' . $report2->id, {
+ $mech->submit_form_ok({ with_fields => {
%problem_prepopulated,
problem_revert_title => 1,
problem_revert_detail => 1,
- });
+ }});
$mech->base_like( qr{\Q$REPORT2_URL\E} );
$report2->discard_changes;
@@ -229,13 +232,12 @@ my $update = create_update();
subtest 'updates' => sub {
- my $MODERATE_UPDATE_URL = sprintf '/moderate/report/%d/update/%d', $report->id, $update->id;
-
subtest 'Update modify text' => sub {
- $mech->post_ok( $MODERATE_UPDATE_URL, {
+ $mech->get_ok($REPORT_URL);
+ $mech->submit_form_ok({ with_fields => {
%update_prepopulated,
update_detail => 'update good good good',
- }) or die $mech->content;
+ }}) or die $mech->content;
$mech->base_like( qr{\Q$REPORT_URL\E} );
$update->discard_changes;
@@ -243,10 +245,10 @@ subtest 'updates' => sub {
};
subtest 'Revert text' => sub {
- $mech->post_ok( $MODERATE_UPDATE_URL, {
+ $mech->submit_form_ok({ with_fields => {
%update_prepopulated,
update_revert_detail => 1,
- });
+ }});
$mech->base_like( qr{\Q$REPORT_URL\E} );
$update->discard_changes;
@@ -258,18 +260,18 @@ subtest 'updates' => sub {
$mech->content_lacks('Posted anonymously')
or die sprintf '%d (%d)', $update->id, $report->comments->count;
- $mech->post_ok( $MODERATE_UPDATE_URL, {
+ $mech->submit_form_ok({ with_fields => {
%update_prepopulated,
update_show_name => 0,
- });
+ }});
$mech->base_like( qr{\Q$REPORT_URL\E} );
$mech->content_contains('Posted anonymously');
- $mech->post_ok( $MODERATE_UPDATE_URL, {
+ $mech->submit_form_ok({ with_fields => {
%update_prepopulated,
update_show_name => 1,
- });
+ }});
$mech->base_like( qr{\Q$REPORT_URL\E} );
$mech->content_lacks('Posted anonymously');
@@ -283,18 +285,18 @@ subtest 'updates' => sub {
$mech->content_contains('Photo of this report')
or die $mech->content;
- $mech->post_ok( $MODERATE_UPDATE_URL, {
+ $mech->submit_form_ok({ with_fields => {
%update_prepopulated,
update_show_photo => 0,
- });
+ }});
$mech->base_like( qr{\Q$REPORT_URL\E} );
$mech->content_lacks('Photo of this report');
- $mech->post_ok( $MODERATE_UPDATE_URL, {
+ $mech->submit_form_ok({ with_fields => {
%update_prepopulated,
update_show_photo => 1,
- });
+ }});
$mech->base_like( qr{\Q$REPORT_URL\E} );
$mech->content_contains('Photo of this report');
@@ -303,10 +305,10 @@ subtest 'updates' => sub {
subtest 'Hide comment' => sub {
$mech->content_contains('update good good bad good');
- $mech->post_ok( $MODERATE_UPDATE_URL, {
+ $mech->submit_form_ok({ with_fields => {
%update_prepopulated,
update_hide => 1,
- });
+ }});
$mech->content_lacks('update good good bad good');
};
@@ -316,11 +318,11 @@ subtest 'updates' => sub {
my $update2 = create_update();
subtest 'Update 2' => sub {
- my $MODERATE_UPDATE2_URL = sprintf '/moderate/report/%d/update/%d', $report->id, $update2->id;
- $mech->post_ok( $MODERATE_UPDATE2_URL, {
+ $mech->get_ok($REPORT_URL);
+ $mech->submit_form_ok({ with_fields => {
%update_prepopulated,
update_detail => 'update good good good',
- }) or die $mech->content;
+ }}) or die $mech->content;
$update2->discard_changes;
is $update2->text, 'update good good [...] good',
diff --git a/t/app/controller/photo.t b/t/app/controller/photo.t
index 425e3c4df..4cec82c44 100644
--- a/t/app/controller/photo.t
+++ b/t/app/controller/photo.t
@@ -40,11 +40,15 @@ subtest "Check multiple upload worked" => sub {
# submit the main form
# can't post_ok as we lose the Content_Type header
# (TODO rewrite with HTTP::Request::Common and request_ok)
+ $mech->get_ok('/report/new?lat=53.4031156&lon=-2.9840579');
+ my ($csrf) = $mech->content =~ /name="token" value="([^"]*)"/;
+
$mech->post( '/report/new',
Content_Type => 'form-data',
Content =>
{
submit_problem => 1,
+ token => $csrf,
title => 'Test',
lat => 53.4031156, lon => -2.9840579, # in Liverpool
pc => 'L1 4LN',
@@ -57,9 +61,6 @@ subtest "Check multiple upload worked" => sub {
email => 'test@example.com',
phone => '',
category => 'Street lighting',
- #password_sign_in => '',
- #password_register => '',
- #remember_me => undef,
}
);
ok $mech->success, 'Made request with multiple photo upload';
diff --git a/t/app/controller/report_updates.t b/t/app/controller/report_updates.t
index 7b4bf7854..2a3c7c0b3 100644
--- a/t/app/controller/report_updates.t
+++ b/t/app/controller/report_updates.t
@@ -510,20 +510,14 @@ subtest 'check non authority user cannot change set state' => sub {
$user->update;
$mech->get_ok("/report/$report_id");
- $mech->post_ok( "/report/update", {
- submit_update => 1,
- id => $report_id,
- name => $user->name,
- may_show_name => 1,
- add_alert => undef,
- photo1 => '',
- photo2 => '',
- photo3 => '',
- update => 'this is a forbidden update',
- state => 'fixed - council',
+ $mech->submit_form_ok( {
+ form_id => 'form_update_form',
+ fields => {
+ may_show_name => 1,
+ update => 'this is a forbidden update',
+ state => 'fixed - council',
},
- 'submitted with state',
- );
+ }, 'submitted with state');
is $mech->uri->path, "/report/update", "at /report/update";
@@ -540,20 +534,14 @@ for my $state ( qw/unconfirmed hidden partial/ ) {
$user->update;
$mech->get_ok("/report/$report_id");
- $mech->post_ok( "/report/update", {
- submit_update => 1,
- id => $report_id,
- name => $user->name,
- may_show_name => 1,
- add_alert => undef,
- photo1 => '',
- photo2 => '',
- photo3 => '',
- update => 'this is a forbidden update',
- state => $state,
+ $mech->submit_form_ok( {
+ form_id => 'form_update_form',
+ fields => {
+ may_show_name => 1,
+ update => 'this is a forbidden update',
+ state => $state,
},
- 'submitted with state',
- );
+ }, 'submitted with state');
is $mech->uri->path, "/report/update", "at /report/update";
@@ -570,10 +558,6 @@ for my $test (
fields => {
name => $user->name,
may_show_name => 1,
- add_alert => undef,
- photo1 => '',
- photo2 => '',
- photo3 => '',
update => 'Set state to investigating',
state => 'investigating',
},
@@ -584,10 +568,6 @@ for my $test (
fields => {
name => $user->name,
may_show_name => 1,
- add_alert => undef,
- photo1 => '',
- photo2 => '',
- photo3 => '',
update => 'Set state to in progress',
state => 'in progress',
},
@@ -598,10 +578,6 @@ for my $test (
fields => {
name => $user->name,
may_show_name => 1,
- add_alert => undef,
- photo1 => '',
- photo2 => '',
- photo3 => '',
update => 'Set state to fixed',
state => 'fixed',
},
@@ -612,10 +588,6 @@ for my $test (
fields => {
name => $user->name,
may_show_name => 1,
- add_alert => undef,
- photo1 => '',
- photo2 => '',
- photo3 => '',
update => 'Set state to action scheduled',
state => 'action scheduled',
},
@@ -626,10 +598,6 @@ for my $test (
fields => {
name => $user->name,
may_show_name => 1,
- add_alert => undef,
- photo1 => '',
- photo2 => '',
- photo3 => '',
update => 'Set state to unable to fix',
state => 'unable to fix',
},
@@ -640,10 +608,6 @@ for my $test (
fields => {
name => $user->name,
may_show_name => 1,
- add_alert => undef,
- photo1 => '',
- photo2 => '',
- photo3 => '',
update => 'Set state to internal referral',
state => 'internal referral',
},
@@ -655,10 +619,6 @@ for my $test (
fields => {
name => $user->name,
may_show_name => 1,
- add_alert => undef,
- photo1 => '',
- photo2 => '',
- photo3 => '',
update => 'Set state to not responsible',
state => 'not responsible',
},
@@ -670,10 +630,6 @@ for my $test (
fields => {
name => $user->name,
may_show_name => 1,
- add_alert => undef,
- photo1 => '',
- photo2 => '',
- photo3 => '',
update => 'Set state to duplicate',
state => 'duplicate',
},
@@ -685,10 +641,6 @@ for my $test (
fields => {
name => $user->name,
may_show_name => 1,
- add_alert => undef,
- photo1 => '',
- photo2 => '',
- photo3 => '',
update => 'Set state to internal referral',
state => 'internal referral',
},
@@ -700,10 +652,6 @@ for my $test (
fields => {
name => $user->name,
may_show_name => 1,
- add_alert => undef,
- photo1 => '',
- photo2 => '',
- photo3 => '',
update => 'Set state to fixed',
state => 'fixed',
},
diff --git a/t/cobrand/zurich.t b/t/cobrand/zurich.t
index cf66136e5..a595f48c9 100644
--- a/t/cobrand/zurich.t
+++ b/t/cobrand/zurich.t
@@ -810,17 +810,12 @@ subtest "photo must be supplied for categories that require it" => sub {
MAPIT_ID_WHITELIST => [ 423017 ],
MAP_TYPE => 'Zurich,OSM',
}, sub {
- $mech->post_ok( '/report/new', {
+ $mech->get_ok('/report/new?lat=47.381817&lon=8.529156');
+ $mech->submit_form_ok({ with_fields => {
detail => 'Problem-Bericht',
- lat => 47.381817,
- lon => 8.529156,
email => 'user@example.org',
- pc => '',
- name => '',
category => 'Graffiti - photo required',
- photo => '',
- submit_problem => 1,
- });
+ }});
is $mech->res->code, 200, "missing photo shouldn't return anything but 200";
$mech->content_contains(_("Photo is required."), 'response should contain photo error message');
};
diff --git a/templates/email/bromley/questionnaire.txt b/templates/email/bromley/questionnaire.txt
index b9d428b98..5c0bd2957 100644
--- a/templates/email/bromley/questionnaire.txt
+++ b/templates/email/bromley/questionnaire.txt
@@ -1,8 +1,9 @@
-Subject: Questionnaire about '[% title %]'
+Subject: Questionnaire about your report: '[% title %]'
-Hi [% name %],
+Hello [% name %],
-[% created %] ago, you reported a problem. To keep the site
+[% created %] ago, you reported a problem, the details of
+which are at the end of this email. To keep the site
up to date and relevant, please fill in a short questionnaire
updating the status of your problem:
@@ -13,8 +14,7 @@ mailbox, please do not reply.
[% signature %]
-
-Your problem was as follows:
+Your report was as follows:
[% title %]
diff --git a/templates/email/default/change_email.txt b/templates/email/default/change_email.txt
new file mode 100644
index 000000000..0c5aeac14
--- /dev/null
+++ b/templates/email/default/change_email.txt
@@ -0,0 +1,11 @@
+Subject: Updating your [% INCLUDE 'site-name.txt' | trim %] email address
+
+Please click on the link below to confirm you wish to update your
+email address on [% INCLUDE 'site-name.txt' | trim %].
+
+[% c.uri_for_action( 'auth/token', token ) %]
+
+[% INCLUDE 'signature.txt' %]
+
+This email was sent automatically, from an unmonitored email account - so
+please do not reply to it.
diff --git a/templates/web/base/admin/body-form.html b/templates/web/base/admin/body-form.html
index 7acfbfdd5..8c4956f7f 100644
--- a/templates/web/base/admin/body-form.html
+++ b/templates/web/base/admin/body-form.html
@@ -236,7 +236,7 @@
<p>
<input type="hidden" name="posted" value="body">
- <input type="hidden" name="token" value="[% token %]">
+ <input type="hidden" name="token" value="[% csrf_token %]">
<input type="submit" value="[% body ? loc('Update body') : loc('Add body') %]">
</p>
</form>
diff --git a/templates/web/base/admin/body.html b/templates/web/base/admin/body.html
index d5e575666..15802fc44 100644
--- a/templates/web/base/admin/body.html
+++ b/templates/web/base/admin/body.html
@@ -97,7 +97,7 @@
<p>
<input type="hidden" name="posted" value="update">
- <input type="hidden" name="token" value="[% token %]">
+ <input type="hidden" name="token" value="[% csrf_token %]">
<input type="submit" name="Update statuses" value="[% loc('Update statuses') %]">
</p>
</form>
@@ -202,7 +202,7 @@
<p>
<input type="hidden" name="posted" value="new" >
- <input type="hidden" name="token" value="[% token %]" >
+ <input type="hidden" name="token" value="[% csrf_token %]" >
<input type="submit" name="Create category" value="[% errors ? loc('Save changes') : loc('Create category') %]" >
</p>
diff --git a/templates/web/base/admin/category_edit.html b/templates/web/base/admin/category_edit.html
index c0bd43ef5..6537fe028 100644
--- a/templates/web/base/admin/category_edit.html
+++ b/templates/web/base/admin/category_edit.html
@@ -22,7 +22,7 @@
<form method="post" action="[% c.uri_for('body', body_id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8">
<p><strong>[% loc('Category:') %] </strong>[% contact.category | html %]
<input type="hidden" name="category" value="[% contact.category | html %]" >
- <input type="hidden" name="token" value="[% token %]" >
+ <input type="hidden" name="token" value="[% csrf_token %]" >
[% IF contact.extra %]
<p><strong>[% loc('Extra data:') %] </strong>
[% USE Dumper %]
diff --git a/templates/web/base/admin/report_edit.html b/templates/web/base/admin/report_edit.html
index c0cdead84..065c6c2ce 100644
--- a/templates/web/base/admin/report_edit.html
+++ b/templates/web/base/admin/report_edit.html
@@ -4,7 +4,7 @@
[% status_message %]
<form method="post" action="[% c.uri_for( 'report_edit', problem.id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8">
- <input type="hidden" name="token" value="[% token %]" >
+ <input type="hidden" name="token" value="[% csrf_token %]" >
<input type="hidden" name="submit" value="1" >
<ul>
[%- cobrand_data = problem.cobrand_data;
diff --git a/templates/web/base/admin/update_edit.html b/templates/web/base/admin/update_edit.html
index a956bb2cb..06bee6010 100644
--- a/templates/web/base/admin/update_edit.html
+++ b/templates/web/base/admin/update_edit.html
@@ -4,7 +4,7 @@
[% status_message %]
<form method="post" action="[% c.uri_for( 'update_edit', update.id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8">
- <input type="hidden" name="token" value="[% token %]" >
+ <input type="hidden" name="token" value="[% csrf_token %]" >
<input type="hidden" name="submit" value="1" >
<ul>
[%- cobrand_data = update.cobrand_data;
diff --git a/templates/web/base/admin/user-form.html b/templates/web/base/admin/user-form.html
index 3956e8533..b863bf96a 100644
--- a/templates/web/base/admin/user-form.html
+++ b/templates/web/base/admin/user-form.html
@@ -1,5 +1,5 @@
<form method="post" action="[% c.uri_for( 'user_edit', user.id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8">
- <input type="hidden" name="token" value="[% token %]" >
+ <input type="hidden" name="token" value="[% csrf_token %]" >
<input type="hidden" name="submit" value="1" >
[% IF c.cobrand.moniker == 'zurich' AND field_errors.email %]
diff --git a/templates/web/base/alert/_list.html b/templates/web/base/alert/_list.html
index 395948248..65bba2fed 100644
--- a/templates/web/base/alert/_list.html
+++ b/templates/web/base/alert/_list.html
@@ -1,3 +1,4 @@
+ <input type="hidden" name="token" value="[% csrf_token %]">
<input type="hidden" name="type" value="local">
<input type="hidden" name="pc" value="[% pc | html %]">
<input type="hidden" name="latitude" value="[% latitude | html %]">
diff --git a/templates/web/base/alert/updates.html b/templates/web/base/alert/updates.html
index 104bfa55a..ecaed37ca 100644
--- a/templates/web/base/alert/updates.html
+++ b/templates/web/base/alert/updates.html
@@ -23,6 +23,7 @@
<input class="green-btn" type="submit" value="[% loc('Subscribe') %]">
</div>
+ <input type="hidden" name="token" value="[% csrf_token %]">
<input type="hidden" name="id" value="[% problem_id | html %]">
<input type="hidden" name="type" value="updates">
</fieldset>
diff --git a/templates/web/base/around/display_location.html b/templates/web/base/around/display_location.html
index 337b97b8e..0ae1aadf5 100755
--- a/templates/web/base/around/display_location.html
+++ b/templates/web/base/around/display_location.html
@@ -41,6 +41,7 @@
[% IF allow_creation %]
<form action="[% c.uri_for('/report/new') %]" method="post" name="mapForm" id="mapForm" enctype="multipart/form-data" class="validate" novalidate>
+ <input type="hidden" name="token" value="[% csrf_token %]">
[% IF c.req.params.map_override %]
<input type="hidden" name="map_override" value="[% c.req.params.map_override | html %]">
[% END %]
diff --git a/templates/web/base/auth/change_email.html b/templates/web/base/auth/change_email.html
new file mode 100644
index 000000000..58c864929
--- /dev/null
+++ b/templates/web/base/auth/change_email.html
@@ -0,0 +1,37 @@
+[% INCLUDE 'header.html', title = loc('Change email address'), bodyclass = 'authpage' %]
+
+<h1>[% loc('Change email address') %]</h1>
+
+[% IF c.req.args.0 == 'success' %]
+ <p class="form-success">[% loc('You have successfully confirmed your email address.') %]</p>
+[% END %]
+
+[% loc('Your email address') %]: [% c.user.email %]
+
+<form action="[% c.uri_for('change_email') %]" method="post" name="change_email">
+ <input type="hidden" name="token" value="[% csrf_token %]">
+
+ <fieldset>
+ [% IF email_error;
+ errors = {
+ missing = loc('Please enter your email'),
+ other = loc('Please check your email address is correct')
+ };
+ loc_email_error = errors.$email_error || errors.other;
+ %]
+ <div class="form-error">[% loc_email_error %]</div>
+ [% END %]
+
+ <div class="form-field">
+ <label for="email">[% loc('New email address:') %]</label>
+ <input type="email" name="email" id="email" value="[% email | html %]">
+ </div>
+ <div class="final-submit">
+ <input type="submit" value="[% loc('Change email address') %]">
+ </div>
+
+ </fieldset>
+</form>
+
+
+[% INCLUDE 'footer.html' %]
diff --git a/templates/web/base/auth/change_password.html b/templates/web/base/auth/change_password.html
index b4170c23e..44b695e0d 100644
--- a/templates/web/base/auth/change_password.html
+++ b/templates/web/base/auth/change_password.html
@@ -3,12 +3,14 @@
<h1>[% loc('Change password') %]</h1>
[% IF password_changed %]
- <p id="fixed">[% loc('Your password has been changed') %]</p>
+ <p class="form-success">[% loc('Your password has been changed') %]</p>
[% END %]
<form action="[% c.uri_for('change_password') %]" method="post" name="change_password" class="fieldset">
+ <input type="hidden" name="token" value="[% csrf_token %]">
+ <fieldset>
[% IF password_error;
errors = {
@@ -29,10 +31,11 @@
<label for="confirm">[% loc('Again:') %]</label>
<input type="password" name="confirm" value="[% confirm | html %]">
</div>
- <div class="checkbox">
+ <div class="final-submit">
<input type="submit" value="[% loc('Change password') %]">
</div>
+ </fieldset>
</form>
diff --git a/templates/web/base/auth/general.html b/templates/web/base/auth/general.html
index 253dc26a1..a8bf8f1e0 100644
--- a/templates/web/base/auth/general.html
+++ b/templates/web/base/auth/general.html
@@ -86,8 +86,15 @@
<input class="green-btn" type="submit" name="sign_in" value="[% loc('Sign in') %]">
</div>
- <input type="checkbox" id="remember_me" name="remember_me" value='1'[% ' checked' IF remember_me %]>
- <label class="inline n" for="remember_me">[% loc('Keep me signed in on this computer') %]</label>
+ <div class="checkbox-group">
+ <input type="checkbox" id="remember_me" name="remember_me" value='1'[% ' checked' IF remember_me %]>
+ <label class="inline n" for="remember_me">[% loc('Keep me signed in on this computer') %]</label>
+ </div>
+
+ <div class="general-notes">
+ <p><strong>[% loc('Forgotten your password?') %]</strong>
+ [% loc('Sign in by email instead, providing a new password. When you click the link in your email, your password will be updated.') %]</p>
+ </div>
</div>
[% END %]
diff --git a/templates/web/base/my/my.html b/templates/web/base/my/my.html
index b93a837ad..9ba9533f8 100644
--- a/templates/web/base/my/my.html
+++ b/templates/web/base/my/my.html
@@ -20,6 +20,7 @@
<p class="my-account-buttons">
<a href="/auth/change_password">[% loc('Change password') %]</a>
+ <a href="/auth/change_email">[% loc('Change email') %]</a>
<a href="/auth/sign_out">[% loc('Sign out') %]</a>
</p>
diff --git a/templates/web/base/report/_main.html b/templates/web/base/report/_main.html
index aaa167108..4821b3fa0 100644
--- a/templates/web/base/report/_main.html
+++ b/templates/web/base/report/_main.html
@@ -5,6 +5,7 @@
[% IF moderating %]
[% original = problem_original %]
<form method="post" action="/moderate/report/[% problem.id %]">
+ <input type="hidden" name="token" value="[% csrf_token %]">
<p class="moderate-display">
<input type="button" class="btn moderate" value="moderate">
</p>
diff --git a/templates/web/base/report/display_tools.html b/templates/web/base/report/display_tools.html
index ed9537184..435bfcbc1 100644
--- a/templates/web/base/report/display_tools.html
+++ b/templates/web/base/report/display_tools.html
@@ -2,6 +2,7 @@
<ul id="key-tools">
[% IF c.user_exists AND c.cobrand.users_can_hide AND c.user.belongs_to_body( c.cobrand.council_id ) %]
<li><form method="post" action="/report/delete/[% problem.id %]" id="remove-from-site-form">
+ <input type="hidden" name="token" value="[% csrf_token %]">
<input type="submit" id="key-tool-report-abuse" class="abuse" value="Remove from site">
</form></li>
[% ELSIF c.cobrand.moniker != 'zurich' %]
@@ -50,6 +51,7 @@
<input type="email" name="rznvy" id="alert_rznvy" value="[% email | html %]" size="30" placeholder="[% loc('Your email') %]">
<input class="green-btn" type="submit" value="[% loc('Subscribe') %]">
</div>
+ <input type="hidden" name="token" value="[% csrf_token %]">
<input type="hidden" name="id" value="[% problem.id %]">
<input type="hidden" name="type" value="updates">
</fieldset>
diff --git a/templates/web/base/report/new/fill_in_details.html b/templates/web/base/report/new/fill_in_details.html
index fc272b533..e980c6065 100644
--- a/templates/web/base/report/new/fill_in_details.html
+++ b/templates/web/base/report/new/fill_in_details.html
@@ -15,16 +15,15 @@
<input type="hidden" name="map_override" value="[% c.req.params.map_override | html %]">
[% END %]
- <input type="hidden" name="pc" value="[% pc | html %]">
-
[% ELSE %]
<form action="[% c.uri_for('/report/new') %]" method="post" name="mapSkippedForm"[% IF c.cobrand.allow_photo_upload %] enctype="multipart/form-data"[% END %] class="validate">
- <input type="hidden" name="pc" value="[% pc | html %]">
<input type="hidden" name="skipped" value="1">
[% END %]
+ <input type="hidden" name="token" value="[% csrf_token %]">
+ <input type="hidden" name="pc" value="[% pc | html %]">
<input type="hidden" name="latitude" id="fixmystreet.latitude" value="[% latitude | html %]">
<input type="hidden" name="longitude" id="fixmystreet.longitude" value="[% longitude | html %]">
diff --git a/templates/web/base/report/update-form.html b/templates/web/base/report/update-form.html
index f6ce265bf..97e0df779 100644
--- a/templates/web/base/report/update-form.html
+++ b/templates/web/base/report/update-form.html
@@ -15,6 +15,7 @@
[% INCLUDE 'errors.html' %]
<form method="post" action="[% c.uri_for( '/report/update' ) %]" id="form_update_form" name="updateForm" class="validate"[% IF c.cobrand.allow_photo_upload %] enctype="multipart/form-data"[% END %]>
+ <input type="hidden" name="token" value="[% csrf_token %]">
<fieldset>
[% IF NOT login_success AND NOT oauth_need_email %]
[% INCLUDE 'report/update/form_update.html' %]
diff --git a/templates/web/base/report/update.html b/templates/web/base/report/update.html
index a09913d39..aaad33b7a 100644
--- a/templates/web/base/report/update.html
+++ b/templates/web/base/report/update.html
@@ -8,6 +8,7 @@
<li class="item-list__item item-list__item--updates">
[% IF moderating; original_update = update.moderation_original_data %]
<form method="post" action="/moderate/report/[% problem.id %]/update/[% update.id %]">
+ <input type="hidden" name="token" value="[% csrf_token %]">
<input type="button" class="btn moderate moderate-display" value="moderate">
<div class="moderate-edit">
<input type="checkbox" class="hide-document" name="update_hide">
diff --git a/templates/web/bromley/report/display.html b/templates/web/bromley/report/display.html
index d46d310cd..f30824385 100644
--- a/templates/web/bromley/report/display.html
+++ b/templates/web/bromley/report/display.html
@@ -30,6 +30,7 @@
[% INCLUDE 'errors.html' %]
<form method="post" action="[% c.uri_for( '/report/update' ) %]" name="updateForm" class="validate"[% IF c.cobrand.allow_photo_upload %] enctype="multipart/form-data"[% END %]>
+ <input type="hidden" name="token" value="[% csrf_token %]">
<fieldset>
<input type="hidden" name="submit_update" value="1">
<input type="hidden" name="id" value="[% problem.id | html %]">
diff --git a/templates/web/eastsussex/report/update-form.html b/templates/web/eastsussex/report/update-form.html
index e4fb47a45..b2c67890f 100644
--- a/templates/web/eastsussex/report/update-form.html
+++ b/templates/web/eastsussex/report/update-form.html
@@ -24,6 +24,7 @@
</p>
<form method="post" action="/report/new">
+ <input type="hidden" name="token" value="[% csrf_token %]">
<input type="hidden" name="latitude" value="[% problem.latitude %]">
<input type="hidden" name="longitude" value="[% problem.longitude %]">
<input type="submit" class="green-btn" value="CREATE A NEW PROBLEM NEARBY">
@@ -56,6 +57,7 @@
[% INCLUDE 'errors.html' %]
<form method="post" action="[% c.uri_for( '/report/update' ) %]" id="form_update_form" name="updateForm" class="validate"[% IF c.cobrand.allow_photo_upload %] enctype="multipart/form-data"[% END %]>
+ <input type="hidden" name="token" value="[% csrf_token %]">
<fieldset>
<input type="hidden" name="submit_update" value="1">
<input type="hidden" name="id" value="[% problem.id | html %]">
diff --git a/templates/web/seesomething/around/display_location.html b/templates/web/seesomething/around/display_location.html
index 3ed7cac46..7886c3a5d 100644
--- a/templates/web/seesomething/around/display_location.html
+++ b/templates/web/seesomething/around/display_location.html
@@ -21,6 +21,7 @@
%]
<form action="[% c.uri_for('/report/new') %]" method="post" name="mapForm" id="mapForm" enctype="multipart/form-data" class="validate" novalidate>
+ <input type="hidden" name="token" value="[% csrf_token %]">
[% IF c.req.params.map_override %]
<input type="hidden" name="map_override" value="[% c.req.params.map_override | html %]">
[% END %]
diff --git a/templates/web/zurich/admin/body-form.html b/templates/web/zurich/admin/body-form.html
index ac2887159..966bdf799 100644
--- a/templates/web/zurich/admin/body-form.html
+++ b/templates/web/zurich/admin/body-form.html
@@ -47,7 +47,7 @@
<p>
<input type="hidden" name="posted" value="body">
- <input type="hidden" name="token" value="[% token %]">
+ <input type="hidden" name="token" value="[% csrf_token %]">
<p>
<input type="submit" value="[% body ? loc('Update body') : loc('Add body') %]">
</p>
diff --git a/templates/web/zurich/admin/body.html b/templates/web/zurich/admin/body.html
index 771f1e537..1a156773d 100644
--- a/templates/web/zurich/admin/body.html
+++ b/templates/web/zurich/admin/body.html
@@ -55,7 +55,7 @@
<p>
<input type="hidden" name="posted" value="new" >
- <input type="hidden" name="token" value="[% token %]" >
+ <input type="hidden" name="token" value="[% csrf_token %]" >
<input type="submit" name="Create category" value="[% errors ? loc('Save changes') : loc('Create category') %]">
</p>
diff --git a/templates/web/zurich/admin/report_edit-sdm.html b/templates/web/zurich/admin/report_edit-sdm.html
index 3cdf3d8c3..b8de2a5ef 100644
--- a/templates/web/zurich/admin/report_edit-sdm.html
+++ b/templates/web/zurich/admin/report_edit-sdm.html
@@ -13,7 +13,7 @@
<div id="map_sidebar">
<form method="post" action="[% c.uri_for( 'report_edit', problem.id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8">
- <input type="hidden" name="token" value="[% token %]" >
+ <input type="hidden" name="token" value="[% csrf_token %]" >
<input type="hidden" name="submit" value="1" >
<div class="admin-report-edit admin-report-edit--details">
diff --git a/templates/web/zurich/admin/report_edit.html b/templates/web/zurich/admin/report_edit.html
index 512ea4708..215373eca 100644
--- a/templates/web/zurich/admin/report_edit.html
+++ b/templates/web/zurich/admin/report_edit.html
@@ -15,7 +15,7 @@
[% pstate = problem.get_extra_metadata('closure_status') || problem.state %]
<form id="report_edit" method="post" action="[% c.uri_for( 'report_edit', problem.id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8">
- <input type="hidden" name="token" value="[% token %]" >
+ <input type="hidden" name="token" value="[% csrf_token %]" >
<input type="hidden" name="submit" value="1" >
<div class="admin-report-edit admin-report-edit--details">
diff --git a/templates/web/zurich/admin/template_edit.html b/templates/web/zurich/admin/template_edit.html
index 1deda6a77..dbad55f08 100644
--- a/templates/web/zurich/admin/template_edit.html
+++ b/templates/web/zurich/admin/template_edit.html
@@ -25,7 +25,7 @@
<textarea name="text" class="required">[% rt.text |html %]</textarea>
</p>
<p>
- <input type="hidden" name="token" value="[% token %]" >
+ <input type="hidden" name="token" value="[% csrf_token %]" >
<input type="submit" name="Edit templates" value="[% rt.id ? loc('Save changes') : loc('Create template') %]" >
</p>
[% IF rt.id %]
diff --git a/templates/web/zurich/admin/update_edit.html b/templates/web/zurich/admin/update_edit.html
index fbd96f3a5..adafff3a8 100644
--- a/templates/web/zurich/admin/update_edit.html
+++ b/templates/web/zurich/admin/update_edit.html
@@ -4,7 +4,7 @@
[% status_message %]
<form method="post" action="[% c.uri_for( 'update_edit', update.id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8">
- <input type="hidden" name="token" value="[% token %]" >
+ <input type="hidden" name="token" value="[% csrf_token %]" >
<input type="hidden" name="submit" value="1" >
<ul>
<li><a href="[% c.uri_for_email( '/report', update.problem_id ) %]#update_[% update.id %]">[% loc('View report on site' )%]</a></li>