File Coverage

blib/lib/Dancer/Plugin/Facebook.pm
Criterion Covered Total %
statement 32 80 40.0
branch 5 26 19.2
condition 2 12 16.6
subroutine 8 13 61.5
pod n/a
total 47 131 35.8


line stmt bran cond sub pod time code
1             package Dancer::Plugin::Facebook;
2             {
3             $Dancer::Plugin::Facebook::VERSION = '0.991';
4             }
5             # ABSTRACT: Manage Facebook interaction within Dancer applications
6              
7 2     2   836870 use Dancer qw{:syntax};
  2         5  
  2         14  
8 2     2   854 use Dancer::Hook;
  2         4  
  2         57  
9 2     2   1925 use Dancer::Plugin;
  2         3138  
  2         175  
10 2     2   1982 use Facebook::Graph;
  2         893744  
  2         67  
11 2     2   22 use Try::Tiny;
  2         4  
  2         2010  
12              
13              
14             my (%config, $fb, $redirect);
15              
16             sub _get_fb {
17 1   50 1   240 debug "Getting fb object [", $fb // "undef", "]";
18              
19             # The first time out, turn our raw, local postback URL into a
20             # fully qualified one (see _do_fb_postback for more explanation).
21 1 50       6029 if ($config{raw_postback}) {
22 0         0 my $url = delete $config{raw_postback};
23             # Place the postback url in $config for object instantiation
24 0         0 $config{postback} = uri_for ($url);
25 0         0 debug "Full postback URL is ", $config{postback};
26             }
27              
28             # We use a before hook to clear a stale FB handle out, and just
29             # use ||= to regenerate as necessary here.
30 1   33     7 $fb ||= do {
31 1         4 my %settings = %config;
32 1 50       6 if (my $access_token = session->{auth}->{facebook}) {
33 0         0 $settings{access_token} = $access_token;
34             }
35 1         557 debug "Creating Facebook::Graph object with settings ", \%settings;
36 1         344 Facebook::Graph->new (%settings);
37             };
38             }
39              
40             sub _get_fb_redirect_url () {
41 0   0 0   0 $redirect ||= do {
42 0         0 my $settings = plugin_setting;
43 0         0 debug "Settings are ", $settings;
44 0 0       0 my @permissions = ref $settings->{permissions} eq "ARRAY" ? @{$settings->{permissions}} : ();
  0         0  
45 0         0 _get_fb->authorize->extend_permissions (@permissions)->uri_as_string;
46             };
47             }
48              
49             sub _do_fb_redirect () {
50 0     0   0 my $url = _get_fb_redirect_url;
51             sub {
52 0     0   0 debug "Redirecting to $url";
53 0         0 redirect $url, 303;
54             }
55 0         0 }
56              
57             sub _do_fb_postback ($) {
58 0     0   0 my $settings = plugin_setting;
59 0         0 debug "Settings are ", $settings;
60              
61 0         0 my ($url) = @_;
62              
63             # We can only determine the relative URL right now, but that's
64             # enough for initializing the route. We put the relative URL
65             # in $config{raw_postback} so that when fb is called for the
66             # first time, which will be within a route handler, we can sub
67             # in the full URL, which is what FB actually needs
68 0 0       0 die "You must give me the postback URL when calling fb_postback" unless ($url);
69 0         0 $config{raw_postback} = $url;
70              
71             # This hook will get called when we successfully authenticate and have
72             # put the token in the session, so the application developer can
73             # retrieve it. It doesn't need to exist if a postback route hasn't been
74             # established
75 0         0 register_hook (['fb_access_token_available']);
76              
77 0   0     0 my $success = $settings->{landing}->{success} || "/";
78 0   0     0 my $failure = $settings->{landing}->{failure} || "/";
79              
80             sub {
81             try {
82 0         0 my $token = _get_fb->request_access_token (params->{code});
83 0         0 session->{auth}->{facebook} = $token->token;
84 0         0 execute_hooks 'fb_access_token_available', $token->token;
85             # Go back wherever
86 0         0 redirect $success;
87             } catch {
88 0         0 redirect $failure;
89 0     0   0 };
90             }
91 0         0 }
92              
93             register setup_fb => sub (;$) {
94 1     1   4421 my ($url) = @_;
95 1         4 debug "Setting up fb access";
96              
97             # We need global access to this, grab it here
98 1         260 my $settings = plugin_setting;
99 1         24 debug "Settings are ", $settings;
100              
101             # Copy our registered application information over
102 1 50       373 if (ref $settings->{application} eq "HASH") {
103 0         0 debug "Setting application information";
104 0 0       0 $config{app_id} = $settings->{application}->{app_id} or die "You didn't give me an app_id for Dancer::Plugin::Facebook";
105 0 0       0 $config{secret} = $settings->{application}->{secret} or die "You didn't give me a secret for Dancer::Plugin::Facebook";
106             }
107              
108             # Set a hook to clear out any old object unless existing tokens in
109             # the object and session match one another. In theory, this means
110             # that absent an access token, we should never replace it.
111 1         4 debug "Setting hook to clear facebook context";
112             hook before => sub {
113 1 50   1   5498 if (defined $fb) {
114 0         0 debug "Considering clearing facebook context";
115 0 0       0 if (defined session->{auth}->{facebook}) {
116 0 0       0 if ($fb->has_access_token) {
117 0 0       0 if ($fb->access_token ne session->{auth}->{facebook}) {
118 0         0 debug "Current FB access token doesn't match";
119 0         0 undef $fb;
120             }
121             } else {
122 0         0 debug "Current FB doesn't have access token";
123 0         0 undef $fb;
124             }
125             } else {
126 0 0       0 if ($fb->has_access_token) {
127 0         0 debug "Current login doesn't have access token";
128 0         0 undef $fb;
129             }
130             }
131             }
132 1         277 };
133              
134             # If the user wants the automatic URL setup
135 1 50       184 if ($url) {
136 0         0 debug "Creating handler for ", $url;
137 0         0 get $url => _do_fb_redirect;
138              
139 0         0 my $postback = "$url/postback";
140 0         0 debug "Creating handler for ", $postback;
141 0         0 get $postback => _do_fb_postback $postback;
142             }
143              
144 1         6 debug "Done setting up fb access";
145             };
146              
147             register fb => \&_get_fb;
148             register fb_redirect => \&_do_fb_redirect;
149             register fb_redirect_url => \&_get_fb_redirect_url;
150             register fb_postback => \&_do_fb_postback;
151             register_plugin;
152              
153              
154             1;
155              
156             __END__