aboutsummaryrefslogtreecommitdiffstats
path: root/perllib/FixMyStreet
diff options
context:
space:
mode:
Diffstat (limited to 'perllib/FixMyStreet')
-rw-r--r--perllib/FixMyStreet/App/Controller/Around.pm7
-rw-r--r--perllib/FixMyStreet/App/Controller/Auth.pm144
-rw-r--r--perllib/FixMyStreet/App/Controller/Dashboard.pm3
-rwxr-xr-xperllib/FixMyStreet/App/Controller/FakeMapit.pm3
-rw-r--r--perllib/FixMyStreet/App/Controller/JSON.pm2
-rw-r--r--perllib/FixMyStreet/App/Controller/Open311.pm2
-rw-r--r--perllib/FixMyStreet/App/Controller/Report.pm4
-rw-r--r--perllib/FixMyStreet/App/Controller/Report/New.pm149
-rw-r--r--perllib/FixMyStreet/App/Controller/Report/Update.pm166
-rw-r--r--perllib/FixMyStreet/App/Controller/Reports.pm3
-rwxr-xr-xperllib/FixMyStreet/App/Controller/Status.pm2
-rw-r--r--perllib/FixMyStreet/App/Controller/Tokens.pm2
-rw-r--r--perllib/FixMyStreet/Cobrand/UK.pm1
-rw-r--r--perllib/FixMyStreet/DB/Result/User.pm10
-rw-r--r--perllib/FixMyStreet/Geocode.pm1
-rw-r--r--perllib/FixMyStreet/Map/OSM/TonerLite.pm2
-rw-r--r--perllib/FixMyStreet/TestMech.pm2
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