· 7 years ago · Apr 08, 2018, 09:40 AM
1### The model ####
2package MyApp::Model::Twitter;
3use Moose;
4use Carp;
5use Net::Twitter;
6use namespace::autoclean;
7
8extends 'Catalyst::Component';
9
10__PACKAGE__->config(
11 session_key => '__twitter_oauth',
12);
13
14sub COMPONENT {
15 my ( $class, $app, $args ) = @_;
16
17 croak "traits required for $class" unless exists $args->{traits};
18
19 push @{$args->{traits}}, 'Catalyst';
20 return Net::Twitter->new({
21 session_key => $class->config->{session_key},
22 %$args
23 });
24}
25
26__PACKAGE__->meta->make_immutable;
27
281;
29
30
31### The Net::Twitter role ###
32package Net::Twitter::Role::Catalyst;
33use Moose::Role;
34use Carp;
35use namespace::autoclean;
36
37=head1 NAME
38
39Net::Twitter::Role::Catalyst
40
41=cut
42
43with 'Net::Twitter::Role::OAuth';
44
45has session_key => (
46 isa => 'Str',
47 is => 'rw',
48 required => 1,
49);
50
51sub twitter_authentication_redirect { shift->_oauth_redirect(get_authentication_url => @_) }
52sub twitter_authorization_redirect { shift->_oauth_redirect(get_authorization_url => @_) }
53
54sub _oauth_redirect {
55 my ( $self, $method, $c, $callback_action ) = @_;
56
57 my $url = $self->$method(callback => $c->uri_for($callback_action));
58 $c->session->{$self->session_key}{oauth_secret} = $self->request_token_secret;
59 $c->res->redirect($url);
60}
61
62sub twitter_login {
63 my ( $self, $c ) = @_;
64
65 my $oauth_token = $c->req->param('oauth_token') and
66 my $oauth_verifier = $c->req->param('oauth_verifier')
67 or croak "Missing oauth paramaters";
68
69 my $oauth_secret = delete $c->session->{$self->session_key}{oauth_secret}
70 or croak "oauth_secret is not in the session data";
71
72 $self->request_token($oauth_token);
73 $self->request_token_secret($oauth_secret);
74
75 my %oauth;
76 @{oauth}{qw/access_token access_secret user_id screen_name/} =
77 $self->request_access_token(verifier => $oauth_verifier);
78
79 return \%oauth;
80}
81
821;
83
84
85### the config ###
86 'Model::Twitter' => {
87 traits => [qw/API::REST/],
88 consumer_key => 'key',
89 consumer_secret => 'secret',
90 useragent_args => { timeout => 15 },
91 },
92
93
94
95### controller usage ###
96sub twitter_auth :Local {
97 my ( $self, $c ) = @_;
98
99 $c->detach('not_found') unless $c->req->method eq 'POST';
100
101 try {
102 $c->model('Twitter')->twitter_authentication_redirect($c, '/login');
103 }
104 catch {
105 $c->log->error("twitter_authentication_redirect failed: $_");
106 $c->flash(error => 'Twitter failed to respond. Please try again');
107 $c->res->redirect($c->uri_for('/'));
108 };
109}
110
111sub login :Local {
112 my ( $self, $c ) = @_;
113
114 # default uri for redirection
115 my $uri = $c->uri_for('/');
116
117 try {
118 my $oauth = $c->model('Twitter')->twitter_login($c);
119
120 my ( $access_token, $access_secret, $user_id, $screen_name ) =
121 @{$c->session}{qw/access_token access_secret user_id screen_name/} =
122 @{$oauth}{qw/access_token access_secret user_id screen_name/};
123
124 if ( $c->authenticate({ id => $user_id }) ) {
125 $c->user->get_object->update({
126 screen_name => $screen_name,
127 oauth_token => $access_token,
128 oauth_secret => $access_secret,
129 });
130 $uri = delete $c->session->{redirect_to_after_login} || $uri;
131 $c->log->debug("Redirecting to $uri");
132 }
133 else {
134 # authenticated with twitter, but not registered, yet
135 $uri = $c->uri_for('register');
136 }
137 }
138 catch {
139 $c->flash(error => 'Twitter authentication failed. Please try again.');
140 return;
141 };
142
143 $c->res->redirect($uri);
144 return;
145}