aboutsummaryrefslogtreecommitdiffstats
path: root/perllib/FixMyStreet/App/Controller/Auth/Phone.pm
blob: 8e3150df9b88e2238b10edbda9cc5ba7fe686192 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package FixMyStreet::App::Controller::Auth::Phone;
use Moose;
use namespace::autoclean;

BEGIN { extends 'Catalyst::Controller'; }

use FixMyStreet::SMS;

=head1 NAME

FixMyStreet::App::Controller::Auth::Phone - Catalyst Controller

=head1 DESCRIPTION

Controller for phone SMS based authentication

=head1 METHODS

=head2 code

Handle the submission of a code sent by text to a mobile number.

=cut

sub code : Path('') {
    my ( $self, $c, $scope, $success_action ) = @_;
    $c->stash->{template} = 'auth/smsform.html';
    $scope ||= 'phone_sign_in';
    $success_action ||= '/auth/process_login';

    my $token = $c->stash->{token} = $c->get_param('token');
    my $code = $c->get_param('code') || '';

    my $data = $c->stash->{token_data} = $c->forward('/auth/get_token', [ $token, $scope ]) || return;

    $c->stash->{incorrect_code} = 1, return if $data->{code} ne $code;

    $c->detach( $success_action, [ $data, 'phone' ] );
}

=head2 sign_in

When signing in with a mobile phone number, we are sent here.
This sends a text to that number with a confirmation code,
and sets up the token/etc to deal with the response.

=cut

sub sign_in : Private {
    my ( $self, $c, $parsed ) = @_;

    unless ($parsed->{phone}) {
        $c->stash->{username_error} = 'other_phone';
        return;
    }

    unless ($parsed->{may_be_mobile}) {
        $c->stash->{username_error} = 'nonmobile';
        return;
    }

    my $password = $c->get_param('password_register');
    if ($password) {
        return unless $c->forward('/auth/test_password', [ $password ]);
    }

    (my $number = $parsed->{phone}->format) =~ s/\s+//g;

    if ( FixMyStreet->config('SIGNUPS_DISABLED')
         && !$c->model('DB::User')->find({ phone => $number })
         && !$c->stash->{current_user} # don't break the change phone flow
    ) {
        $c->stash->{template} = 'auth/token.html';
        return;
    }

    my $user_params = {};
    $user_params->{password} = $password if $password;
    my $user = $c->model('DB::User')->new( $user_params );

    my $token_data = {
        phone => $number,
        r => $c->get_param('r'),
        name => $c->get_param('name'),
        password => $user->password,
    };
    if ($c->stash->{current_user}) {
        $token_data->{old_user_id} = $c->stash->{current_user}->id;
        $token_data->{r} = 'auth/change_phone/success';
    }

    $c->forward('send_token', [ $token_data, 'phone_sign_in', $number ]);
}

sub send_token : Private {
    my ( $self, $c, $token_data, $token_scope, $to ) = @_;

    my $result = FixMyStreet::SMS->send_token($token_data, $token_scope, $to);
    if ($result->{error}) {
        $c->log->debug("Failure sending text containing code *$result->{random}*");
        $c->stash->{sms_error} = $result->{error};
        $c->stash->{username_error} = 'sms_failed';
        return;
    }
    $c->stash->{token} = $result->{token};
    $c->log->debug("Sending text containing code *$result->{random}*");
    $c->stash->{template} = 'auth/smsform.html';
}

__PACKAGE__->meta->make_immutable;

1;