diff options
Diffstat (limited to 'perllib')
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Auth.pm | 109 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Photo.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Report/New.pm | 15 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Report/Update.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Tokens.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Model/PhotoSet.pm | 10 |
6 files changed, 117 insertions, 23 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Auth.pm b/perllib/FixMyStreet/App/Controller/Auth.pm index 9e8fb29aa..c5a6cf9bf 100644 --- a/perllib/FixMyStreet/App/Controller/Auth.pm +++ b/perllib/FixMyStreet/App/Controller/Auth.pm @@ -9,6 +9,7 @@ use Net::Domain::TLD; use mySociety::AuthToken; use JSON::MaybeXS; use Net::Facebook::Oauth2; +use Net::Twitter::Lite::WithAPIv1_1; =head1 NAME @@ -38,6 +39,7 @@ sub general : Path : Args(0) { # 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'); @@ -133,6 +135,8 @@ sub email_sign_in : Private { }; $token_data->{facebook_id} = $c->session->{oauth}{facebook_id} 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}; my $token_obj = $c->model('DB::Token')->create({ scope => 'email_sign_in', @@ -180,6 +184,7 @@ sub token : Path('/M') : Args(1) { $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; $c->authenticate( { email => $user->email }, 'no_password' ); @@ -203,7 +208,7 @@ sub fb : Private { } sub facebook_sign_in : Private { - my( $self, $c ) = @_; + my ( $self, $c ) = @_; my $fb = $c->forward('/auth/fb'); my $url = $fb->get_authorization_url(scope => ['email']); @@ -223,17 +228,9 @@ Handles the Facebook callback request and completes the authentication sequence. =cut sub facebook_callback: Path('/auth/Facebook') : Args(0) { - my( $self, $c ) = @_; + 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; - } - } + $c->detach('oauth_failure') if $c->get_param('error_code'); my $fb = $c->forward('/auth/fb'); my $access_token; @@ -250,12 +247,92 @@ sub facebook_callback: Path('/auth/Facebook') : Args(0) { $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}; + $c->forward('oauth_success', [ 'facebook', $info->{id}, $info->{name}, $email ]); +} + +=head2 twitter_sign_in + +Starts the Twitter authentication sequence. + +=cut + +sub tw : Private { + my ($self, $c) = @_; + Net::Twitter::Lite::WithAPIv1_1->new( + ssl => 1, + consumer_key => $c->config->{TWITTER_KEY}, + consumer_secret => $c->config->{TWITTER_SECRET}, + ); +} + +sub twitter_sign_in : Private { + my ( $self, $c ) = @_; + + my $twitter = $c->forward('/auth/tw'); + my $url = $twitter->get_authentication_url(callback => $c->uri_for('/auth/Twitter')); + + my %oauth; + $oauth{return_url} = $c->get_param('r'); + $oauth{detach_to} = $c->stash->{detach_to}; + $oauth{detach_args} = $c->stash->{detach_args}; + $oauth{token} = $twitter->request_token; + $oauth{token_secret} = $twitter->request_token_secret; + $c->session->{oauth} = \%oauth; + $c->res->redirect($url); +} + +=head2 twitter_callback + +Handles the Twitter callback request and completes the authentication sequence. + +=cut + +sub twitter_callback: Path('/auth/Twitter') : Args(0) { + my ( $self, $c ) = @_; + + my $request_token = $c->req->param('oauth_token'); + my $verifier = $c->req->param('oauth_verifier'); + my $oauth = $c->session->{oauth}; + + $c->detach('oauth_failure') if $c->get_param('denied') || $request_token ne $oauth->{token}; + + my $twitter = $c->forward('/auth/tw'); + $twitter->request_token($oauth->{token}); + $twitter->request_token_secret($oauth->{token_secret}); + + eval { + # request_access_token no longer returns UID or name + $twitter->request_access_token(verifier => $verifier); + }; + if ($@) { + ($c->stash->{message} = $@) =~ s/at [^ ]*Auth.pm.*//; + $c->stash->{template} = 'errors/generic.html'; + $c->detach; + } + + my $info = $twitter->verify_credentials(); + $c->forward('oauth_success', [ 'twitter', $info->{id}, $info->{name} ]); +} + +sub oauth_failure : Private { + my ( $self, $c ) = @_; + + $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; + } +} + +sub oauth_success : Private { + my ($self, $c, $type, $uid, $name, $email) = @_; my $user; if ($email) { + # Only Facebook gets here # 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 } ); @@ -267,14 +344,14 @@ sub facebook_callback: Path('/auth/Facebook') : Args(0) { $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 } ); + $user = $c->model('DB::User')->find( { $type . '_id' => $uid } ); if ($user) { - # Matching Facebook ID in our database + # Matching 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->session->{oauth}{$type . '_id'} = $uid; $c->stash->{oauth_need_email} = 1; } } diff --git a/perllib/FixMyStreet/App/Controller/Photo.pm b/perllib/FixMyStreet/App/Controller/Photo.pm index 59f54bad7..d24d3ff71 100644 --- a/perllib/FixMyStreet/App/Controller/Photo.pm +++ b/perllib/FixMyStreet/App/Controller/Photo.pm @@ -140,7 +140,7 @@ sub process_photo_upload_or_cache : Private { /^photo/ ? # photo, photo1, photo2 etc. ($c->req->upload($_)) : () } sort $c->req->upload), - split /,/, ($c->get_param('upload_fileid') || '') + grep { $_ } split /,/, ($c->get_param('upload_fileid') || '') ); my $photoset = FixMyStreet::App::Model::PhotoSet->new({ diff --git a/perllib/FixMyStreet/App/Controller/Report/New.pm b/perllib/FixMyStreet/App/Controller/Report/New.pm index 7126e962e..5df182506 100644 --- a/perllib/FixMyStreet/App/Controller/Report/New.pm +++ b/perllib/FixMyStreet/App/Controller/Report/New.pm @@ -221,7 +221,7 @@ sub category_extras_ajax : Path('category_extras') : Args(0) { $c->forward('setup_categories_and_bodies'); $c->forward('check_for_category'); - my $category = $c->stash->{category}; + my $category = $c->stash->{category} || ""; my $category_extra = ''; my $generate; if ( $c->stash->{category_extras}->{$category} && @{ $c->stash->{category_extras}->{$category} } >= 1 ) { @@ -616,7 +616,16 @@ sub setup_categories_and_bodies : Private { $c->stash->{unresponsive} = {}; if (keys %bodies == 1 && $first_body->send_method && $first_body->send_method eq 'Refused') { - $c->stash->{unresponsive}{ALL} = $first_body->id; + # If there's only one body, and it's set to refused, we can show the + # message immediately, before they select a category. + if ($c->action->name eq 'category_extras_ajax' && $c->req->method eq 'POST') { + # The mobile app doesn't currently use this, in which case make + # sure the message is output, either below with a category, or when + # a blank category call is made. + $c->stash->{unresponsive}{""} = $first_body->id; + } else { + $c->stash->{unresponsive}{ALL} = $first_body->id; + } } # keysort does not appear to obey locale so use strcoll (see i18n.t) @@ -1009,6 +1018,8 @@ sub tokenize_user : Private { }; $c->stash->{token_data}{facebook_id} = $c->session->{oauth}{facebook_id} if $c->get_param('oauth_need_email') && $c->session->{oauth}{facebook_id}; + $c->stash->{token_data}{twitter_id} = $c->session->{oauth}{twitter_id} + if $c->get_param('oauth_need_email') && $c->session->{oauth}{twitter_id}; } =head2 save_user_and_report diff --git a/perllib/FixMyStreet/App/Controller/Report/Update.pm b/perllib/FixMyStreet/App/Controller/Report/Update.pm index 8d6bc2019..af4ccff03 100644 --- a/perllib/FixMyStreet/App/Controller/Report/Update.pm +++ b/perllib/FixMyStreet/App/Controller/Report/Update.pm @@ -382,6 +382,8 @@ sub tokenize_user : Private { }; $c->stash->{token_data}{facebook_id} = $c->session->{oauth}{facebook_id} if $c->get_param('oauth_need_email') && $c->session->{oauth}{facebook_id}; + $c->stash->{token_data}{twitter_id} = $c->session->{oauth}{twitter_id} + if $c->get_param('oauth_need_email') && $c->session->{oauth}{twitter_id}; } =head2 save_update diff --git a/perllib/FixMyStreet/App/Controller/Tokens.pm b/perllib/FixMyStreet/App/Controller/Tokens.pm index eb35fd152..38f344250 100644 --- a/perllib/FixMyStreet/App/Controller/Tokens.pm +++ b/perllib/FixMyStreet/App/Controller/Tokens.pm @@ -106,6 +106,7 @@ sub confirm_problem : Path('/P') { $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->twitter_id( $data->{twitter_id} ) if $data->{twitter_id}; $problem->user->update; } $c->authenticate( { email => $problem->user->email }, 'no_password' ); @@ -232,6 +233,7 @@ sub confirm_update : Path('/C') { $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->twitter_id( $data->{twitter_id} ) if $data->{twitter_id}; $comment->user->update; } diff --git a/perllib/FixMyStreet/App/Model/PhotoSet.pm b/perllib/FixMyStreet/App/Model/PhotoSet.pm index 41d02d2a7..243675f2c 100644 --- a/perllib/FixMyStreet/App/Model/PhotoSet.pm +++ b/perllib/FixMyStreet/App/Model/PhotoSet.pm @@ -176,7 +176,7 @@ has ids => ( # Arrayref of $fileid tuples (always, so post upload/raw data proc } my ($fileid, $type) = split /\./, $part; $type ||= 'jpeg'; - if (length($fileid) == 40) { + if ($fileid && length($fileid) == 40) { my $file = $self->get_file($fileid, $type); if ($file->exists) { $file->basename; @@ -185,7 +185,7 @@ has ids => ( # Arrayref of $fileid tuples (always, so post upload/raw data proc (); } } else { - warn sprintf "Received bad photo hash of length %d", length($fileid); + # A bad hash, probably a bot spamming with bad data. (); } }); @@ -265,13 +265,15 @@ sub remove_images { --$dec; } + $self->delete_cached(); + + return undef if !@images; + my $new_set = (ref $self)->new({ data_items => \@images, object => $self->object, }); - $self->delete_cached(); - return $new_set->data; # e.g. new comma-separated fileid } |