aboutsummaryrefslogtreecommitdiffstats
path: root/perllib/FixMyStreet/App/Controller/Tokens.pm
blob: 6feae9e9cdb7befca8827278f595e1a7c981b8a8 (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
113
114
package FixMyStreet::App::Controller::Tokens;
use Moose;
use namespace::autoclean;

BEGIN { extends 'Catalyst::Controller'; }

use FixMyStreet::Alert;

=head1 NAME

FixMyStreet::App::Controller::Tokens - Handle auth tokens

=head1 DESCRIPTION

Act on the various tokens that can be submitted.

=head1 METHODS

=cut

=head2 confirm_problem

    /[Pp]/([0-9A-Za-z]{16,18}).*$

Confirm a problem - url appears in emails sent to users after they create the
problem but are not logged in.

=cut

sub confirm_problem : Path('/P') {
    my ( $self, $c, $token_code ) = @_;

    my $auth_token =
      $c->forward( 'load_auth_token', [ $token_code, 'problem' ] );

    # Load the problem
    my $problem_id = $auth_token->data;
    my $problem = $c->model('DB::Problem')->find( { id => $problem_id } )
      || $c->detach('token_error');
    $c->stash->{problem} = $problem;

    # check that this email or domain are not the cause of abuse. If so hide it.
    if ( $problem->is_from_abuser ) {
        $problem->update(
            { state => 'hidden', lastupdate => \'ms_current_timestamp()' } );
        $c->stash->{template} = 'tokens/abuse.html';
        return;
    }

    # We have a problem - confirm it if needed!
    $problem->update(
        {
            state      => 'confirmed',
            confirmed  => \'ms_current_timestamp()',
            lastupdate => \'ms_current_timestamp()',
        }
    ) if $problem->state eq 'unconfirmed';

    # Subscribe problem reporter to email updates
    my $alert_id =
      FixMyStreet::Alert::create( $problem->user->email, 'new_updates',
        $problem->cobrand, $problem->cobrand_data, $problem_id );
    FixMyStreet::Alert::confirm($alert_id);

    # log the problem creation user in to the site
    $c->authenticate( { email => $problem->user->email }, 'no_password' );

    return 1;
}

=head2 load_auth_token

    my $auth_token =
      $c->forward( 'load_auth_token', [ $token_code, $token_scope ] );


Load the token if possible. If token is not found, or not valid detach to a nice
error message.

=cut

sub load_auth_token : Private {
    my ( $self, $c, $token_code, $scope ) = @_;

    # clean the token of bad chars (in case of email client issues)
    $token_code ||= '';
    $token_code =~ s{[^a-zA-Z0-9]+}{}g;

    # try to load the token
    my $token = $c->model('DB::Token')->find(
        {
            scope => $scope,
            token => $token_code,
        }
    ) || $c->detach('token_error');

    return $token;
}

=head2 token_error

Display an error page saying that there is something wrong with the token.

=cut

sub token_error : Private {
    my ( $self, $c ) = @_;
    $c->stash->{template} = 'tokens/error.html';
    $c->detach;
}

__PACKAGE__->meta->make_immutable;

1;