diff options
Diffstat (limited to 'perllib/FixMyStreet')
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Around.pm | 7 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Auth.pm | 144 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Dashboard.pm | 3 | ||||
-rwxr-xr-x | perllib/FixMyStreet/App/Controller/FakeMapit.pm | 3 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/JSON.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Open311.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Report.pm | 4 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Report/New.pm | 149 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Report/Update.pm | 166 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Reports.pm | 3 | ||||
-rwxr-xr-x | perllib/FixMyStreet/App/Controller/Status.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Tokens.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/UK.pm | 1 | ||||
-rw-r--r-- | perllib/FixMyStreet/DB/Result/User.pm | 10 | ||||
-rw-r--r-- | perllib/FixMyStreet/Geocode.pm | 1 | ||||
-rw-r--r-- | perllib/FixMyStreet/Map/OSM/TonerLite.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/TestMech.pm | 2 |
17 files changed, 370 insertions, 133 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Around.pm b/perllib/FixMyStreet/App/Controller/Around.pm index 4aa695ae5..5ccab4047 100644 --- a/perllib/FixMyStreet/App/Controller/Around.pm +++ b/perllib/FixMyStreet/App/Controller/Around.pm @@ -6,6 +6,7 @@ BEGIN { extends 'Catalyst::Controller'; } use FixMyStreet::Map; use Encode; +use JSON::MaybeXS; use Utils; =head1 NAME @@ -306,7 +307,7 @@ sub ajax : Path('/ajax') { # JSON encode the response my $json = { pins => $pins }; $json->{current} = $on_map_list_html if $on_map_list_html; - my $body = JSON->new->utf8(1)->encode($json); + my $body = encode_json($json); $c->res->body($body); } @@ -363,9 +364,7 @@ sub _geocode : Private { $response = \@addresses; } - my $body = JSON->new->utf8(1)->encode( - $response - ); + my $body = encode_json($response); $c->res->body($body); } diff --git a/perllib/FixMyStreet/App/Controller/Auth.pm b/perllib/FixMyStreet/App/Controller/Auth.pm index 6de416c53..9e8fb29aa 100644 --- a/perllib/FixMyStreet/App/Controller/Auth.pm +++ b/perllib/FixMyStreet/App/Controller/Auth.pm @@ -7,7 +7,8 @@ BEGIN { extends 'Catalyst::Controller'; } use Email::Valid; use Net::Domain::TLD; use mySociety::AuthToken; -use JSON; +use JSON::MaybeXS; +use Net::Facebook::Oauth2; =head1 NAME @@ -36,6 +37,8 @@ sub general : Path : Args(0) { return unless $c->req->method eq 'POST'; # decide which action to take + $c->detach('facebook_sign_in') if $c->get_param('facebook_sign_in'); + my $clicked_password = $c->get_param('sign_in'); my $clicked_email = $c->get_param('email_sign_in'); my $data_password = $c->get_param('password_sign_in'); @@ -122,18 +125,19 @@ sub email_sign_in : Private { if $c->get_param('password_register'); my $user = $c->model('DB::User')->new( $user_params ); - my $token_obj = $c->model('DB::Token') # - ->create( - { - scope => 'email_sign_in', - data => { - email => $good_email, - r => $c->get_param('r'), - name => $c->get_param('name'), - password => $user->password, - } - } - ); + my $token_data = { + email => $good_email, + r => $c->get_param('r'), + name => $c->get_param('name'), + password => $user->password, + }; + $token_data->{facebook_id} = $c->session->{oauth}{facebook_id} + if $c->get_param('oauth_need_email') && $c->session->{oauth}{facebook_id}; + + my $token_obj = $c->model('DB::Token')->create({ + scope => 'email_sign_in', + data => $token_data, + }); $c->stash->{token} = $token_obj->token; $c->send_email( 'login.txt', { to => $good_email } ); @@ -175,6 +179,7 @@ sub token : Path('/M') : Args(1) { my $user = $c->model('DB::User')->find_or_create( { 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->update; $c->authenticate( { email => $user->email }, 'no_password' ); @@ -182,6 +187,113 @@ sub token : Path('/M') : Args(1) { $c->detach( 'redirect_on_signin', [ $data->{r} ] ); } +=head2 facebook_sign_in + +Starts the Facebook authentication sequence. + +=cut + +sub fb : Private { + my ($self, $c) = @_; + Net::Facebook::Oauth2->new( + application_id => $c->config->{FACEBOOK_APP_ID}, + application_secret => $c->config->{FACEBOOK_APP_SECRET}, + callback => $c->uri_for('/auth/Facebook'), + ); +} + +sub facebook_sign_in : Private { + my( $self, $c ) = @_; + + my $fb = $c->forward('/auth/fb'); + my $url = $fb->get_authorization_url(scope => ['email']); + + my %oauth; + $oauth{return_url} = $c->get_param('r'); + $oauth{detach_to} = $c->stash->{detach_to}; + $oauth{detach_args} = $c->stash->{detach_args}; + $c->session->{oauth} = \%oauth; + $c->res->redirect($url); +} + +=head2 facebook_callback + +Handles the Facebook callback request and completes the authentication sequence. + +=cut + +sub facebook_callback: Path('/auth/Facebook') : Args(0) { + my( $self, $c ) = @_; + + if ( $c->get_param('error_code') ) { + $c->stash->{oauth_failure} = 1; + if ($c->session->{oauth}{detach_to}) { + $c->detach($c->session->{oauth}{detach_to}, $c->session->{oauth}{detach_args}); + } else { + $c->stash->{template} = 'auth/general.html'; + $c->detach; + } + } + + my $fb = $c->forward('/auth/fb'); + my $access_token; + eval { + $access_token = $fb->get_access_token(code => $c->get_param('code')); + }; + if ($@) { + ($c->stash->{message} = $@) =~ s/at [^ ]*Auth.pm.*//; + $c->stash->{template} = 'errors/generic.html'; + $c->detach; + } + + # save this token in session + $c->session->{oauth}{token} = $access_token; + + my $info = $fb->get('https://graph.facebook.com/me?fields=name,email')->as_hash(); + my $name = $info->{name}; + my $email = lc ($info->{email} || ""); + my $uid = $info->{id}; + + my $user; + if ($email) { + # We've got an ID and an email address + # Remove any existing mention of this ID + my $existing = $c->model('DB::User')->find( { facebook_id => $uid } ); + $existing->update( { facebook_id => undef } ) if $existing; + # Get or create a user, give it this Facebook ID + $user = $c->model('DB::User')->find_or_new( { email => $email } ); + $user->facebook_id($uid); + $user->name($name); + $user->in_storage() ? $user->update : $user->insert; + } else { + # We've got an ID, but no email + $user = $c->model('DB::User')->find( { facebook_id => $uid } ); + if ($user) { + # Matching Facebook ID in our database + $user->name($name); + $user->update; + } else { + # No matching ID, store ID for use later + $c->session->{oauth}{facebook_id} = $uid; + $c->stash->{oauth_need_email} = 1; + } + } + + # If we've got here with a full user, log in + if ($user) { + $c->authenticate( { email => $user->email }, 'no_password' ); + $c->stash->{login_success} = 1; + } + + if ($c->session->{oauth}{detach_to}) { + $c->detach($c->session->{oauth}{detach_to}, $c->session->{oauth}{detach_args}); + } elsif ($c->stash->{oauth_need_email}) { + $c->stash->{template} = 'auth/general.html'; + } else { + $c->detach( 'redirect_on_signin', [ $c->session->{oauth}{return_url} ] ); + } +} + =head2 redirect_on_signin Used after signing in to take the person back to where they were. @@ -275,7 +387,7 @@ sub ajax_sign_in : Path('ajax/sign_in') { $return->{error} = 1; } - my $body = JSON->new->utf8(1)->encode( $return ); + my $body = encode_json($return); $c->res->content_type('application/json; charset=utf-8'); $c->res->body($body); @@ -287,7 +399,7 @@ sub ajax_sign_out : Path('ajax/sign_out') { $c->logout(); - my $body = JSON->new->utf8(1)->encode( { signed_out => 1 } ); + my $body = encode_json( { signed_out => 1 } ); $c->res->content_type('application/json; charset=utf-8'); $c->res->body($body); @@ -305,7 +417,7 @@ sub ajax_check_auth : Path('ajax/check_auth') { $code = 200; } - my $body = JSON->new->utf8(1)->encode( $data ); + my $body = encode_json($data); $c->res->content_type('application/json; charset=utf-8'); $c->res->code($code); $c->res->body($body); diff --git a/perllib/FixMyStreet/App/Controller/Dashboard.pm b/perllib/FixMyStreet/App/Controller/Dashboard.pm index faddaa89e..9189b28e5 100644 --- a/perllib/FixMyStreet/App/Controller/Dashboard.pm +++ b/perllib/FixMyStreet/App/Controller/Dashboard.pm @@ -4,6 +4,7 @@ use namespace::autoclean; use DateTime; use File::Slurp; +use JSON::MaybeXS; BEGIN { extends 'Catalyst::Controller'; } @@ -40,7 +41,7 @@ sub example : Local : Args(0) { my $data = File::Slurp::read_file( FixMyStreet->path_to( 'data/dashboard.json' )->stringify ); - my $j = JSON->new->utf8->decode($data); + my $j = decode_json($data); if ( !$c->stash->{ward} && !$c->stash->{category} ) { $c->stash->{problems} = $j->{counts_all}; } else { diff --git a/perllib/FixMyStreet/App/Controller/FakeMapit.pm b/perllib/FixMyStreet/App/Controller/FakeMapit.pm index 253c75ba4..a4adadd09 100755 --- a/perllib/FixMyStreet/App/Controller/FakeMapit.pm +++ b/perllib/FixMyStreet/App/Controller/FakeMapit.pm @@ -1,6 +1,7 @@ package FixMyStreet::App::Controller::FakeMapit; use Moose; use namespace::autoclean; +use JSON::MaybeXS; BEGIN { extends 'Catalyst::Controller'; } @@ -22,7 +23,7 @@ my $area = { "name" => "Everywhere", "type" => "ZZZ", "id" => 161 }; sub output : Private { my ( $self, $c, $data ) = @_; - my $body = JSON->new->utf8(1)->encode( $data ); + my $body = encode_json($data); $c->res->content_type('application/json; charset=utf-8'); $c->res->body( $body ); } diff --git a/perllib/FixMyStreet/App/Controller/JSON.pm b/perllib/FixMyStreet/App/Controller/JSON.pm index be738bb8b..d3cd33546 100644 --- a/perllib/FixMyStreet/App/Controller/JSON.pm +++ b/perllib/FixMyStreet/App/Controller/JSON.pm @@ -4,7 +4,7 @@ use namespace::autoclean; BEGIN { extends 'Catalyst::Controller'; } -use JSON; +use JSON::MaybeXS; use DateTime; use DateTime::Format::ISO8601; use List::MoreUtils 'uniq'; diff --git a/perllib/FixMyStreet/App/Controller/Open311.pm b/perllib/FixMyStreet/App/Controller/Open311.pm index 96066ca93..f35dc64a5 100644 --- a/perllib/FixMyStreet/App/Controller/Open311.pm +++ b/perllib/FixMyStreet/App/Controller/Open311.pm @@ -4,7 +4,7 @@ use utf8; use Moose; use namespace::autoclean; -use JSON; +use JSON::MaybeXS; use XML::Simple; use DateTime::Format::W3CDTF; diff --git a/perllib/FixMyStreet/App/Controller/Report.pm b/perllib/FixMyStreet/App/Controller/Report.pm index d7cae05d4..5cc44bb8f 100644 --- a/perllib/FixMyStreet/App/Controller/Report.pm +++ b/perllib/FixMyStreet/App/Controller/Report.pm @@ -2,6 +2,8 @@ package FixMyStreet::App::Controller::Report; use Moose; use namespace::autoclean; +use JSON::MaybeXS; + BEGIN { extends 'Catalyst::Controller'; } =head1 NAME @@ -184,7 +186,7 @@ sub format_problem_for_display : Private { if ( $c->stash->{ajax} ) { $c->res->content_type('application/json; charset=utf-8'); - my $content = JSON->new->utf8(1)->encode( + my $content = encode_json( { report => $c->cobrand->problem_as_hashref( $problem, $c ), updates => $c->cobrand->updates_as_hashref( $problem, $c ), diff --git a/perllib/FixMyStreet/App/Controller/Report/New.pm b/perllib/FixMyStreet/App/Controller/Report/New.pm index db524ada4..bab0f0fd0 100644 --- a/perllib/FixMyStreet/App/Controller/Report/New.pm +++ b/perllib/FixMyStreet/App/Controller/Report/New.pm @@ -12,7 +12,7 @@ use mySociety::MaPit; use Path::Class; use Utils; use mySociety::EmailUtil; -use JSON; +use JSON::MaybeXS; =head1 NAME @@ -164,9 +164,7 @@ sub report_new_ajax : Path('mobile') : Args(0) { sub send_json_response : Private { my ( $self, $c ) = @_; - my $body = JSON->new->utf8(1)->encode( - $c->stash->{json_response}, - ); + my $body = encode_json($c->stash->{json_response}); $c->res->content_type('application/json; charset=utf-8'); $c->res->body($body); } @@ -178,9 +176,7 @@ sub report_form_ajax : Path('ajax') : Args(0) { # work out the location for this report and do some checks if ( ! $c->forward('determine_location') ) { - my $body = JSON->new->utf8(1)->encode( { - error => $c->stash->{location_error}, - } ); + my $body = encode_json({ error => $c->stash->{location_error} }); $c->res->content_type('application/json; charset=utf-8'); $c->res->body($body); return; @@ -197,7 +193,7 @@ sub report_form_ajax : Path('ajax') : Args(0) { my $extra_titles_list = $c->cobrand->title_list($c->stash->{all_areas}); - my $body = JSON->new->utf8(1)->encode( + my $body = encode_json( { councils_text => $councils_text, category => $category, @@ -216,11 +212,7 @@ sub category_extras_ajax : Path('category_extras') : Args(0) { $c->forward('initialize_report'); if ( ! $c->forward('determine_location') ) { - my $body = JSON->new->utf8(1)->encode( - { - error => _("Sorry, we could not find that location."), - } - ); + my $body = encode_json({ error => _("Sorry, we could not find that location.") }); $c->res->content_type('application/json; charset=utf-8'); $c->res->body($body); return 1; @@ -244,11 +236,7 @@ sub category_extras_ajax : Path('category_extras') : Args(0) { $category_extra = $c->render_fragment( 'report/new/category_extras.html'); } - my $body = JSON->new->utf8(1)->encode( - { - category_extra => $category_extra, - } - ); + my $body = encode_json({ category_extra => $category_extra }); $c->res->content_type('application/json; charset=utf-8'); $c->res->body($body); @@ -403,6 +391,12 @@ sub report_import : Path('/import') { return 1; } +sub oauth_callback : Private { + my ( $self, $c, $token_code ) = @_; + $c->stash->{oauth_report} = $token_code; + $c->detach('report_new'); +} + =head2 initialize_report Create the report and set up some basics in it. If there is a partial report @@ -448,9 +442,6 @@ sub initialize_report : Private { # save the token to delete at the end $c->stash->{partial_token} = $token if $report; - # Stash the photo IDs for "already got" display - $c->stash->{upload_fileid} = $report->get_photoset->data; - } else { # no point keeping it if it is done. $token->delete; @@ -458,18 +449,25 @@ sub initialize_report : Private { } } - if ( !$report ) { + if (!$report && $c->stash->{oauth_report}) { + my $auth_token = $c->forward( '/tokens/load_auth_token', + [ $c->stash->{oauth_report}, 'problem/social' ] ); + $report = $c->model("DB::Problem")->new($auth_token->data); + } - # If we didn't find a partial then create a new one + if ($report) { + # Stash the photo IDs for "already got" display + $c->stash->{upload_fileid} = $report->get_photoset->data; + } else { + # If we didn't find one otherwise, start with a blank report $report = $c->model('DB::Problem')->new( {} ); + } - # If we have a user logged in let's prefill some values for them. - if ( $c->user ) { - my $user = $c->user->obj; - $report->user($user); - $report->name( $user->name ); - } - + # If we have a user logged in let's prefill some values for them. + if (!$report->user && $c->user) { + my $user = $c->user->obj; + $report->user($user); + $report->name( $user->name ); } if ( $c->get_param('first_name') && $c->get_param('last_name') ) { @@ -1001,6 +999,13 @@ sub check_for_errors : Private { delete $field_errors{name}; } + # if using social login then we don't care about name and email errors + $c->stash->{is_social_user} = $c->get_param('facebook_sign_in') || $c->get_param('twitter_sign_in'); + if ( $c->stash->{is_social_user} ) { + delete $field_errors{name}; + delete $field_errors{email}; + } + # add the photo error if there is one. if ( my $photo_error = delete $c->stash->{photo_error} ) { $field_errors{photo} = $photo_error; @@ -1014,6 +1019,19 @@ sub check_for_errors : Private { return; } +# Store changes in token for when token is validated. +sub tokenize_user : Private { + my ($self, $c, $report) = @_; + $c->stash->{token_data} = { + name => $report->user->name, + phone => $report->user->phone, + password => $report->user->password, + title => $report->user->title, + }; + $c->stash->{token_data}{facebook_id} = $c->session->{oauth}{facebook_id} + if $c->get_param('oauth_need_email') && $c->session->{oauth}{facebook_id}; +} + =head2 save_user_and_report Save the user and the report. @@ -1025,7 +1043,41 @@ before or they are currently logged in. Otherwise discard any changes. sub save_user_and_report : Private { my ( $self, $c ) = @_; - my $report = $c->stash->{report}; + my $report = $c->stash->{report}; + + # If there was a photo add that + if ( my $fileid = $c->stash->{upload_fileid} ) { + $report->photo($fileid); + } + + # Set a default if possible + $report->category( _('Other') ) unless $report->category; + + # Set unknown to DB unknown + $report->bodies_str( undef ) if $report->bodies_str eq '-1'; + + # if there is a Message Manager message ID, pass it back to the client view + if ($c->cobrand->moniker eq 'fixmybarangay' && $c->get_param('external_source_id') =~ /^\d+$/) { + $c->stash->{external_source_id} = $c->get_param('external_source_id'); + $report->external_source_id( $c->get_param('external_source_id') ); + $report->external_source( $c->config->{MESSAGE_MANAGER_URL} ) ; + } + + if ( $c->stash->{is_social_user} ) { + my $token = $c->model("DB::Token")->create( { + scope => 'problem/social', + data => { $report->get_inflated_columns }, + } ); + + $c->stash->{detach_to} = '/report/new/oauth_callback'; + $c->stash->{detach_args} = [$token->token]; + + if ( $c->get_param('facebook_sign_in') ) { + $c->detach('/auth/facebook_sign_in'); + } elsif ( $c->get_param('twitter_sign_in') ) { + $c->detach('/auth/twitter_sign_in'); + } + } # Save or update the user if appropriate if ( $c->cobrand->never_confirm_reports ) { @@ -1035,15 +1087,10 @@ sub save_user_and_report : Private { $report->user->insert(); } $report->confirm(); + } elsif ( !$report->user->in_storage ) { # User does not exist. - # Store changes in token for when token is validated. - $c->stash->{token_data} = { - name => $report->user->name, - phone => $report->user->phone, - password => $report->user->password, - title => $report->user->title, - }; + $c->forward('tokenize_user', [ $report ]); $report->user->name( undef ); $report->user->phone( undef ); $report->user->password( '', 1 ); @@ -1060,35 +1107,11 @@ sub save_user_and_report : Private { } else { # User exists and we are not logged in as them. - # Store changes in token for when token is validated. - $c->stash->{token_data} = { - name => $report->user->name, - phone => $report->user->phone, - password => $report->user->password, - title => $report->user->title, - }; + $c->forward('tokenize_user', [ $report ]); $report->user->discard_changes(); $c->log->info($report->user->id . ' exists, but is not logged in for this report'); } - # If there was a photo add that too - if ( my $fileid = $c->stash->{upload_fileid} ) { - $report->photo($fileid); - } - - # Set a default if possible - $report->category( _('Other') ) unless $report->category; - - # Set unknown to DB unknown - $report->bodies_str( undef ) if $report->bodies_str eq '-1'; - - # if there is a Message Manager message ID, pass it back to the client view - if ($c->cobrand->moniker eq 'fixmybarangay' && $c->get_param('external_source_id') =~ /^\d+$/) { - $c->stash->{external_source_id} = $c->get_param('external_source_id'); - $report->external_source_id( $c->get_param('external_source_id') ); - $report->external_source( $c->config->{MESSAGE_MANAGER_URL} ) ; - } - # save the report; $report->in_storage ? $report->update : $report->insert(); diff --git a/perllib/FixMyStreet/App/Controller/Report/Update.pm b/perllib/FixMyStreet/App/Controller/Report/Update.pm index 445723fec..45d924335 100644 --- a/perllib/FixMyStreet/App/Controller/Report/Update.pm +++ b/perllib/FixMyStreet/App/Controller/Report/Update.pm @@ -20,12 +20,16 @@ Creates an update to a report sub report_update : Path : Args(0) { my ( $self, $c ) = @_; - $c->forward( '/report/load_problem_or_display_error', [ $c->get_param('id') ] ); + $c->forward('initialize_update'); + $c->forward('load_problem'); + $c->forward('check_form_submitted') + or $c->go( '/report/display', [ $c->stash->{problem}->id ] ); + $c->forward('process_update'); $c->forward('process_user'); $c->forward('/photo/process_photo'); $c->forward('check_for_errors') - or $c->go( '/report/display', [ $c->get_param('id') ] ); + or $c->go( '/report/display', [ $c->stash->{problem}->id ] ); $c->forward('save_update'); $c->forward('redirect_or_confirm_creation'); @@ -151,19 +155,46 @@ sub process_user : Private { return 1; } -=head2 process_update +=head2 oauth_callback -Take the submitted params and create a new update item. Does not save -anything to the database. +Called when we successfully login via OAuth. Stores the token so we can look up +what we have so far. -NB: relies on their being a problem and update_user in the stash. May -want to move adding these elsewhere +=cut + +sub oauth_callback : Private { + my ( $self, $c, $token_code ) = @_; + $c->stash->{oauth_update} = $token_code; + $c->detach('report_update'); +} + +=head2 initialize_update + +Create an initial update object, either empty or from stored OAuth data. =cut -sub process_update : Private { +sub initialize_update : Private { my ( $self, $c ) = @_; + my $update; + if ($c->stash->{oauth_update}) { + my $auth_token = $c->forward( '/tokens/load_auth_token', + [ $c->stash->{oauth_update}, 'update/social' ] ); + $update = $c->model("DB::Comment")->new($auth_token->data); + } + + if ($update) { + $c->stash->{upload_fileid} = $update->get_photoset->data; + } else { + $update = $c->model('DB::Comment')->new({ + state => 'unconfirmed', + cobrand => $c->cobrand->moniker, + cobrand_data => '', + lang => $c->stash->{lang_code}, + }); + } + if ( $c->get_param('first_name') && $c->get_param('last_name') ) { my $first_name = $c->get_param('first_name'); my $last_name = $c->get_param('last_name'); @@ -173,6 +204,48 @@ sub process_update : Private { $c->stash->{last_name} = $last_name; } + $c->stash->{update} = $update; +} + +=head2 load_problem + +Our update could be prefilled, or we could be submitting a form containing an +ID. Look up the relevant report either way. + +=cut + +sub load_problem : Private { + my ( $self, $c ) = @_; + + my $update = $c->stash->{update}; + # Problem ID could come from existing update in token, or from query parameter + my $problem_id = $update->problem_id || $c->get_param('id'); + $c->forward( '/report/load_problem_or_display_error', [ $problem_id ] ); + $update->problem($c->stash->{problem}); +} + +=head2 check_form_submitted + +This makes sure we only proceed to processing if we've had the form submitted +(we may have come here via an OAuth login, for example). + +=cut + +sub check_form_submitted : Private { + my ( $self, $c ) = @_; + return $c->get_param('submit_update') || ''; +} + +=head2 process_update + +Take the submitted params and updates our update item. Does not save +anything to the database. + +=cut + +sub process_update : Private { + my ( $self, $c ) = @_; + my %params = map { $_ => $c->get_param($_) } ( 'update', 'name', 'fixed', 'state', 'reopen' ); @@ -184,20 +257,12 @@ sub process_update : Private { $params{reopen} = 0 unless $c->user && $c->user->id == $c->stash->{problem}->user->id; - my $update = $c->model('DB::Comment')->new( - { - text => $params{update}, - name => $name, - problem => $c->stash->{problem}, - state => 'unconfirmed', - mark_fixed => $params{fixed} ? 1 : 0, - mark_open => $params{reopen} ? 1 : 0, - cobrand => $c->cobrand->moniker, - cobrand_data => '', - lang => $c->stash->{lang_code}, - anonymous => $anonymous, - } - ); + my $update = $c->stash->{update}; + $update->text($params{update}); + $update->name($name); + $update->mark_fixed($params{fixed} ? 1 : 0); + $update->mark_open($params{reopen} ? 1 : 0); + $update->anonymous($anonymous); if ( $params{state} ) { $params{state} = 'fixed - council' @@ -241,7 +306,6 @@ sub process_update : Private { $c->log->debug( 'name is ' . $c->get_param('name') ); - $c->stash->{update} = $update; $c->stash->{add_alert} = $c->get_param('add_alert'); return 1; @@ -283,6 +347,13 @@ sub check_for_errors : Private { %{ $c->stash->{update}->check_for_errors }, ); + # if using social login then we don't care about name and email errors + $c->stash->{is_social_user} = $c->get_param('facebook_sign_in') || $c->get_param('twitter_sign_in'); + if ( $c->stash->{is_social_user} ) { + delete $field_errors{name}; + delete $field_errors{email}; + } + if ( my $photo_error = delete $c->stash->{photo_error} ) { $field_errors{photo} = $photo_error; } @@ -302,6 +373,17 @@ sub check_for_errors : Private { return; } +# Store changes in token for when token is validated. +sub tokenize_user : Private { + my ($self, $c, $update) = @_; + $c->stash->{token_data} = { + name => $update->user->name, + password => $update->user->password, + }; + $c->stash->{token_data}{facebook_id} = $c->session->{oauth}{facebook_id} + if $c->get_param('oauth_need_email') && $c->session->{oauth}{facebook_id}; +} + =head2 save_update Save the update and the user as appropriate. @@ -313,6 +395,27 @@ sub save_update : Private { my $update = $c->stash->{update}; + # If there was a photo add that too + if ( my $fileid = $c->stash->{upload_fileid} ) { + $update->photo($fileid); + } + + if ( $c->stash->{is_social_user} ) { + my $token = $c->model("DB::Token")->create( { + scope => 'update/social', + data => { $update->get_inflated_columns }, + } ); + + $c->stash->{detach_to} = '/report/update/oauth_callback'; + $c->stash->{detach_args} = [$token->token]; + + if ( $c->get_param('facebook_sign_in') ) { + $c->detach('/auth/facebook_sign_in'); + } elsif ( $c->get_param('twitter_sign_in') ) { + $c->detach('/auth/twitter_sign_in'); + } + } + if ( $c->cobrand->never_confirm_updates ) { if ( $update->user->in_storage() ) { $update->user->update(); @@ -322,11 +425,7 @@ sub save_update : Private { $update->confirm(); } elsif ( !$update->user->in_storage ) { # User does not exist. - # Store changes in token for when token is validated. - $c->stash->{token_data} = { - name => $update->user->name, - password => $update->user->password, - }; + $c->forward('tokenize_user', [ $update ]); $update->user->name( undef ); $update->user->password( '', 1 ); $update->user->insert; @@ -338,19 +437,10 @@ sub save_update : Private { $update->confirm; } else { # User exists and we are not logged in as them. - # Store changes in token for when token is validated. - $c->stash->{token_data} = { - name => $update->user->name, - password => $update->user->password, - }; + $c->forward('tokenize_user', [ $update ]); $update->user->discard_changes(); } - # If there was a photo add that too - if ( my $fileid = $c->stash->{upload_fileid} ) { - $update->photo($fileid); - } - if ( $update->in_storage ) { $update->update; } diff --git a/perllib/FixMyStreet/App/Controller/Reports.pm b/perllib/FixMyStreet/App/Controller/Reports.pm index 407fc625e..027b0d5a4 100644 --- a/perllib/FixMyStreet/App/Controller/Reports.pm +++ b/perllib/FixMyStreet/App/Controller/Reports.pm @@ -3,6 +3,7 @@ use Moose; use namespace::autoclean; use File::Slurp; +use JSON::MaybeXS; use List::MoreUtils qw(any); use POSIX qw(strcoll); use RABX; @@ -68,7 +69,7 @@ sub index : Path : Args(0) { my $data = File::Slurp::read_file( FixMyStreet->path_to( '../data/all-reports.json' )->stringify ); - my $j = JSON->new->utf8->decode($data); + my $j = decode_json($data); $c->stash->{fixed} = $j->{fixed}; $c->stash->{open} = $j->{open}; }; diff --git a/perllib/FixMyStreet/App/Controller/Status.pm b/perllib/FixMyStreet/App/Controller/Status.pm index 8a84a1666..931c7bd47 100755 --- a/perllib/FixMyStreet/App/Controller/Status.pm +++ b/perllib/FixMyStreet/App/Controller/Status.pm @@ -3,7 +3,7 @@ use Moose; use namespace::autoclean; use HTTP::Negotiate; -use JSON; +use JSON::MaybeXS; BEGIN { extends 'Catalyst::Controller'; } diff --git a/perllib/FixMyStreet/App/Controller/Tokens.pm b/perllib/FixMyStreet/App/Controller/Tokens.pm index b1d60fe32..eb35fd152 100644 --- a/perllib/FixMyStreet/App/Controller/Tokens.pm +++ b/perllib/FixMyStreet/App/Controller/Tokens.pm @@ -105,6 +105,7 @@ sub confirm_problem : Path('/P') { $problem->user->phone( $data->{phone} ) if $data->{phone}; $problem->user->password( $data->{password}, 1 ) if $data->{password}; $problem->user->title( $data->{title} ) if $data->{title}; + $problem->user->facebook_id( $data->{facebook_id} ) if $data->{facebook_id}; $problem->user->update; } $c->authenticate( { email => $problem->user->email }, 'no_password' ); @@ -230,6 +231,7 @@ sub confirm_update : Path('/C') { if ( $data->{name} || $data->{password} ) { $comment->user->name( $data->{name} ) if $data->{name}; $comment->user->password( $data->{password}, 1 ) if $data->{password}; + $comment->user->facebook_id( $data->{facebook_id} ) if $data->{facebook_id}; $comment->user->update; } diff --git a/perllib/FixMyStreet/Cobrand/UK.pm b/perllib/FixMyStreet/Cobrand/UK.pm index 2473f386f..824590d38 100644 --- a/perllib/FixMyStreet/Cobrand/UK.pm +++ b/perllib/FixMyStreet/Cobrand/UK.pm @@ -1,6 +1,7 @@ package FixMyStreet::Cobrand::UK; use base 'FixMyStreet::Cobrand::Default'; +use JSON::MaybeXS; use mySociety::MaPit; use mySociety::VotingArea; diff --git a/perllib/FixMyStreet/DB/Result/User.pm b/perllib/FixMyStreet/DB/Result/User.pm index f08b666c8..ddf986c47 100644 --- a/perllib/FixMyStreet/DB/Result/User.pm +++ b/perllib/FixMyStreet/DB/Result/User.pm @@ -32,9 +32,15 @@ __PACKAGE__->add_columns( { data_type => "boolean", default_value => \"false", is_nullable => 0 }, "title", { data_type => "text", is_nullable => 1 }, + "twitter_id", + { data_type => "bigint", is_nullable => 1 }, + "facebook_id", + { data_type => "bigint", is_nullable => 1 }, ); __PACKAGE__->set_primary_key("id"); __PACKAGE__->add_unique_constraint("users_email_key", ["email"]); +__PACKAGE__->add_unique_constraint("users_facebook_id_key", ["facebook_id"]); +__PACKAGE__->add_unique_constraint("users_twitter_id_key", ["twitter_id"]); __PACKAGE__->has_many( "admin_logs", "FixMyStreet::DB::Result::AdminLog", @@ -84,8 +90,8 @@ __PACKAGE__->has_many( ); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2014-07-29 13:54:07 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Y41/jGp93IxSpyJ/o6Q1gQ +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2015-12-09 16:02:08 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:hCq6ZDZfV/6iiu3HFhPPOg __PACKAGE__->add_columns( "password" => { diff --git a/perllib/FixMyStreet/Geocode.pm b/perllib/FixMyStreet/Geocode.pm index aac52fbaa..4470ecbca 100644 --- a/perllib/FixMyStreet/Geocode.pm +++ b/perllib/FixMyStreet/Geocode.pm @@ -11,6 +11,7 @@ use Digest::MD5 qw(md5_hex); use Encode; use File::Slurp; use File::Path (); +use JSON::MaybeXS; use LWP::Simple qw($ua); use URI::Escape; use FixMyStreet::Geocode::Bing; diff --git a/perllib/FixMyStreet/Map/OSM/TonerLite.pm b/perllib/FixMyStreet/Map/OSM/TonerLite.pm index 543cd6002..b0d12c453 100644 --- a/perllib/FixMyStreet/Map/OSM/TonerLite.pm +++ b/perllib/FixMyStreet/Map/OSM/TonerLite.pm @@ -1,5 +1,3 @@ -#!/usr/bin/perl -# # FixMyStreet:Map::OSM::TonerLite # OSM TonerLite maps on FixMyStreet. # diff --git a/perllib/FixMyStreet/TestMech.pm b/perllib/FixMyStreet/TestMech.pm index d3adce08b..9d836ca4d 100644 --- a/perllib/FixMyStreet/TestMech.pm +++ b/perllib/FixMyStreet/TestMech.pm @@ -14,7 +14,7 @@ use Test::More; use Web::Scraper; use Carp; use Email::Send::Test; -use JSON; +use JSON::MaybeXS; =head1 NAME |