diff options
author | Matthew Somerville <matthew-github@dracos.co.uk> | 2015-07-09 20:33:51 +0100 |
---|---|---|
committer | Matthew Somerville <matthew@mysociety.org> | 2015-07-10 13:49:25 +0100 |
commit | 2ac123a2e0e4594099a11057647ffc190219993d (patch) | |
tree | 4cfa460cb78461b6c5958f6d06dce497d11378a5 /perllib | |
parent | a978c0a1ad216f7004ef88b8a58b9731242155dc (diff) |
Alter token logging in and timeout behaviour.
Restrict email_sign_in token to one day, unused confirmation tokens to
one month. Used tokens will redirect to the created thing but not log
in; don't log in with alert links (unsubscribe link never expires, reply
link will still show "reopen" tickbox).
Diffstat (limited to 'perllib')
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Auth.pm | 5 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Report.pm | 4 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Report/Update.pm | 4 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Tokens.pm | 107 | ||||
-rw-r--r-- | perllib/FixMyStreet/DB/ResultSet/AlertType.pm | 7 |
5 files changed, 93 insertions, 34 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Auth.pm b/perllib/FixMyStreet/App/Controller/Auth.pm index 66cf3979c..63bf91ff5 100644 --- a/perllib/FixMyStreet/App/Controller/Auth.pm +++ b/perllib/FixMyStreet/App/Controller/Auth.pm @@ -155,6 +155,11 @@ sub token : Path('/M') : Args(1) { return; } + if ( $token_obj->created < DateTime->now->subtract( days => 1 ) ) { + $c->stash->{token_not_found} = 1; + return; + } + # Sign out in case we are another user $c->logout(); diff --git a/perllib/FixMyStreet/App/Controller/Report.pm b/perllib/FixMyStreet/App/Controller/Report.pm index 97250f859..7b001ee4c 100644 --- a/perllib/FixMyStreet/App/Controller/Report.pm +++ b/perllib/FixMyStreet/App/Controller/Report.pm @@ -151,6 +151,10 @@ sub load_updates : Private { @combined = map { $_->[1] } sort { $a->[0] <=> $b->[0] } @combined; $c->stash->{updates} = \@combined; + if ($c->sessionid && $c->flash->{alert_to_reporter}) { + $c->stash->{alert_to_reporter} = 1; + } + return 1; } diff --git a/perllib/FixMyStreet/App/Controller/Report/Update.pm b/perllib/FixMyStreet/App/Controller/Report/Update.pm index 79fed0fd1..17aec2113 100644 --- a/perllib/FixMyStreet/App/Controller/Report/Update.pm +++ b/perllib/FixMyStreet/App/Controller/Report/Update.pm @@ -420,8 +420,8 @@ happen before calling this. sub signup_for_alerts : Private { my ( $self, $c ) = @_; + my $update = $c->stash->{update}; if ( $c->stash->{add_alert} ) { - my $update = $c->stash->{update}; my $options = { user => $update->user, alert_type => 'new_updates', @@ -438,7 +438,7 @@ sub signup_for_alerts : Private { } $alert->confirm(); - } elsif ( $c->user && ( my $alert = $c->user->alert_for_problem($c->stash->{update}->problem_id) ) ) { + } elsif ( my $alert = $update->user->alert_for_problem($update->problem_id) ) { $alert->disable(); } diff --git a/perllib/FixMyStreet/App/Controller/Tokens.pm b/perllib/FixMyStreet/App/Controller/Tokens.pm index 96bcedd37..21c269502 100644 --- a/perllib/FixMyStreet/App/Controller/Tokens.pm +++ b/perllib/FixMyStreet/App/Controller/Tokens.pm @@ -43,17 +43,17 @@ sub confirm_problem : Path('/P') { # Load the problem my $data = $auth_token->data; - my $problem_id = ref $data ? $data->{id} : $data; + $data = { id => $data } unless ref $data; + + my $problem_id = $data->{id}; # Look at all problems, not just cobrand, in case am approving something we don't actually show my $problem = $c->model('DB::Problem')->find( { id => $problem_id } ) || $c->detach('token_error'); $c->stash->{report} = $problem; - if ( $problem->state eq 'unconfirmed' && $auth_token->created < DateTime->now->subtract( months => 1 ) ) { - $c->stash->{template} = 'errors/generic.html'; - $c->stash->{message} = _("I'm afraid we couldn't validate that token, as the report was made too long ago."); - return; - } + $c->detach('token_too_old') + if $problem->state eq 'unconfirmed' + && $auth_token->created < DateTime->now->subtract( months => 1 ); # check that this email or domain are not the cause of abuse. If so hide it. if ( $problem->is_from_abuser ) { @@ -71,7 +71,7 @@ sub confirm_problem : Path('/P') { confirmed => \'ms_current_timestamp()', } ); - if ( ref($data) && ( $data->{name} || $data->{password} ) ) { + if ( $data->{name} || $data->{password} ) { $problem->user->name( $data->{name} ) if $data->{name}; $problem->user->phone( $data->{phone} ) if $data->{phone}; $problem->user->update; @@ -80,21 +80,26 @@ sub confirm_problem : Path('/P') { return 1; } - # We have a problem - confirm it if needed! - my $old_state = $problem->state; + if ($problem->state ne 'unconfirmed') { + my $report_uri = $c->cobrand->base_url_for_report( $problem ) . $problem->url; + $c->res->redirect($report_uri); + return; + } + + # We have an unconfirmed problem $problem->update( { state => 'confirmed', confirmed => \'ms_current_timestamp()', lastupdate => \'ms_current_timestamp()', } - ) if $problem->state eq 'unconfirmed'; + ); # Subscribe problem reporter to email updates $c->forward( '/report/new/create_reporter_alert' ); # log the problem creation user in to the site - if ( ref($data) && ( $data->{name} || $data->{password} ) ) { + if ( $data->{name} || $data->{password} ) { $problem->user->name( $data->{name} ) if $data->{name}; $problem->user->phone( $data->{phone} ) if $data->{phone}; $problem->user->password( $data->{password}, 1 ) if $data->{password}; @@ -104,11 +109,6 @@ sub confirm_problem : Path('/P') { $c->authenticate( { email => $problem->user->email }, 'no_password' ); $c->set_session_cookie_expire(0); - if ( FixMyStreet::DB::Result::Problem->visible_states()->{$old_state} ) { - my $report_uri = $c->cobrand->base_url_for_report( $problem ) . $problem->url; - $c->res->redirect($report_uri); - } - $c->stash->{created_report} = 'fromemail'; return 1; } @@ -149,21 +149,27 @@ sub confirm_alert : Path('/A') { my $auth_token = $c->forward( 'load_auth_token', [ $token_code, 'alert' ] ); - # Load the problem + # Load the alert my $alert_id = $auth_token->data->{id}; $c->stash->{confirm_type} = $auth_token->data->{type}; my $alert = $c->model('DB::Alert')->find( { id => $alert_id } ) || $c->detach('token_error'); $c->stash->{alert} = $alert; + $c->detach('token_too_old') + if $c->stash->{confirm_type} ne 'unsubscribe' + && $auth_token->created < DateTime->now->subtract( months => 1 ); + # check that this email or domain are not the cause of abuse. If so hide it. if ( $alert->is_from_abuser ) { $c->stash->{template} = 'tokens/abuse.html'; return; } - $c->authenticate( { email => $alert->user->email }, 'no_password' ); - $c->set_session_cookie_expire(0); + if (!$alert->confirmed && $c->stash->{confirm_type} ne 'unsubscribe') { + $c->authenticate( { email => $alert->user->email }, 'no_password' ); + $c->set_session_cookie_expire(0); + } $c->forward('/alert/confirm'); @@ -195,7 +201,7 @@ sub confirm_update : Path('/C') { my $auth_token = $c->forward( 'load_auth_token', [ $token_code, 'comment' ] ); - # Load the problem + # Load the update my $data = $auth_token->data; my $comment_id = $data->{id}; $c->stash->{add_alert} = $data->{add_alert}; @@ -204,26 +210,32 @@ sub confirm_update : Path('/C') { || $c->detach('token_error'); $c->stash->{update} = $comment; + $c->detach('token_too_old') + if $comment->state ne 'confirmed' + && $auth_token->created < DateTime->now->subtract( months => 1 ); + # check that this email or domain are not the cause of abuse. If so hide it. if ( $comment->is_from_abuser ) { $c->stash->{template} = 'tokens/abuse.html'; return; } + if ( $comment->state ne 'unconfirmed' ) { + my $report_uri = $c->cobrand->base_url_for_report( $comment->problem ) . $comment->problem->url; + $c->res->redirect($report_uri); + return; + } + if ( $data->{name} || $data->{password} ) { $comment->user->name( $data->{name} ) if $data->{name}; $comment->user->password( $data->{password}, 1 ) if $data->{password}; $comment->user->update; } + $c->authenticate( { email => $comment->user->email }, 'no_password' ); $c->set_session_cookie_expire(0); - if ( $comment->confirmed ) { - my $report_uri = $c->cobrand->base_url_for_report( $comment->problem ) . $comment->problem->url; - $c->res->redirect($report_uri); - } else { - $c->forward('/report/update/confirm'); - } + $c->forward('/report/update/confirm'); return 1; } @@ -234,6 +246,7 @@ sub load_questionnaire : Private { my $auth_token = $c->forward( 'load_auth_token', [ $token_code, 'questionnaire' ] ); $c->stash->{id} = $auth_token->data; $c->stash->{token} = $token_code; + $c->stash->{token_obj} = $auth_token; my $questionnaire = $c->model('DB::Questionnaire')->find( { id => $c->stash->{id} }, @@ -247,11 +260,43 @@ sub questionnaire : Path('/Q') : Args(1) { my ( $self, $c, $token_code ) = @_; $c->forward( 'load_questionnaire', [ $token_code ] ); - $c->authenticate( { email => $c->stash->{questionnaire}->problem->user->email }, 'no_password' ); - $c->set_session_cookie_expire(0); + $c->detach('token_too_old') if $c->stash->{token_obj}->created < DateTime->now->subtract( months => 1 ); + + my $questionnaire = $c->stash->{questionnaire}; + if (!$questionnaire->whenanswered) { + $c->authenticate( { email => $questionnaire->problem->user->email }, 'no_password' ); + $c->set_session_cookie_expire(0); + } $c->forward( '/questionnaire/show' ); } +=head2 alert_to_reporter + + /R/([0-9A-Za-z]{16,18}).*$ + +A link in an update alert to a problem reporter - show the "reopen report" +tickbox but don't log the person in. + +=cut + +sub alert_to_reporter : Path('/R') { + my ( $self, $c, $token_code ) = @_; + + my $auth_token = + $c->forward( 'load_auth_token', [ $token_code, 'alert_to_reporter' ] ); + my $data = $auth_token->data; + + my $problem_id = $data->{id}; + my $problem = $c->model('DB::Problem')->find( { id => $problem_id } ) + || $c->detach('token_error'); + + $c->detach('token_too_old') if $auth_token->created < DateTime->now->subtract( months => 1 ); + + $c->flash->{alert_to_reporter} = 1; + my $report_uri = $c->cobrand->base_url_for_report( $problem ) . $problem->url; + $c->res->redirect($report_uri); +} + =head2 load_auth_token my $auth_token = @@ -298,6 +343,12 @@ sub token_error : Private { $c->stash->{template} = 'tokens/error.html'; } +sub token_too_old : Private { + my ( $self, $c ) = @_; + $c->stash->{token_not_found} = 1; + $c->stash->{template} = 'auth/token.html'; +} + __PACKAGE__->meta->make_immutable; 1; diff --git a/perllib/FixMyStreet/DB/ResultSet/AlertType.pm b/perllib/FixMyStreet/DB/ResultSet/AlertType.pm index ad180cbd5..0b430008a 100644 --- a/perllib/FixMyStreet/DB/ResultSet/AlertType.pm +++ b/perllib/FixMyStreet/DB/ResultSet/AlertType.pm @@ -103,13 +103,12 @@ sub email_alerts ($) { } ); $data{alert_email} = $user->email; my $token_obj = FixMyStreet::App->model('DB::Token')->create( { - scope => 'email_sign_in', + scope => 'alert_to_reporter', data => { - email => $user->email, - r => 'report/' . $row->{id}, + id => $row->{id}, } } ); - $data{problem_url} = $url . "/M/" . $token_obj->token; + $data{problem_url} = $url . "/R/" . $token_obj->token; } else { $data{problem_url} = $url . "/report/" . $row->{id}; } |