File Coverage

blib/lib/HTML/FormHandlerX/Field/noCAPTCHA.pm
Criterion Covered Total %
statement 30 40 75.0
branch 7 12 58.3
condition 4 16 25.0
subroutine 9 12 75.0
pod 1 1 100.0
total 51 81 62.9


line stmt bran cond sub pod time code
1             package HTML::FormHandlerX::Field::noCAPTCHA;
2              
3 8     8   304223 use Moose;
  8         21  
  8         74  
4 8     8   53172 use Moose::Util::TypeConstraints;
  8         21  
  8         72  
5 8     8   18980 use Captcha::noCAPTCHA;
  8         232832  
  8         263  
6 8     8   59 use namespace::autoclean;
  8         19  
  8         91  
7              
8             our $VERSION = '0.12'; # VERSION
9              
10             extends 'HTML::FormHandler::Field';
11              
12             has '+widget' => ( default => 'noCAPTCHA' );
13             has '+input_param' => ( default => 'g-recaptcha-response' );
14             has '+messages' => ( default => sub { {required => 'You must prove your Humanity!'} });
15             has '+required' => ( default => 1 );
16              
17             has [qw/site_key secret_key/] => (is=>'rw', isa=>'Str', required => 1,lazy_build => 1);
18             has 'theme' => (is=>'ro',isa=> enum([qw(dark light)]),default => 'light');
19             has 'noscript' => (is=>'ro',isa=> 'Bool',default => 0);
20             has 'remote_address' => (is=>'ro', isa=>'Str', required => 1, lazy_build => 1);
21             has 'api_url' => (is=>'ro', isa=>'Str', required => 1, lazy_build => 1);
22             has 'api_timeout' => (is=>'ro', isa=>'Int', required => 1, lazy_build => 1);
23             has 'g_captcha_message' => (is=>'ro', isa=>'Str', default=>'You\'ve failed to prove your Humanity!');
24             has 'g_captcha_failure_message' => (is=>'ro', isa=>'Str', default=>'We\'ve had trouble processing your request, please try again.');
25             has 'config_key' => (is=>'ro', isa=>'Str', default=> __PACKAGE__);
26             has '_nocaptcha' => (is=>'ro', isa=>'Captcha::noCAPTCHA', lazy_build => 1);
27              
28             sub _build_remote_address {
29 0     0   0 my ($self) = @_;
30 0 0       0 return '' unless ($self->form->ctx);
31 0         0 return $self->form->ctx->req->address;
32             }
33              
34             sub _build_secret_key {
35 0     0   0 my ($self) = @_;
36 0   0     0 my $config = $self->_g_captcha_config || return;
37 0         0 return $config->{secret_key};
38             }
39              
40             sub _build_site_key {
41 0     0   0 my ($self) = @_;
42 0   0     0 my $config = $self->_g_captcha_config || return;
43 0         0 return $config->{site_key};
44             }
45              
46             sub _build_api_url {
47 3     3   12 my ($self) = @_;
48 3         20 my $config = $self->_g_captcha_config;
49 3 50 33     307 return $config && $config->{api_url} ? $config->{api_url} : 'https://www.google.com/recaptcha/api/siteverify';
50             }
51              
52             sub _build_api_timeout {
53 5     5   15 my ($self) = @_;
54 5         23 my $config = $self->_g_captcha_config;
55 5 50 33     423 return $config && exists $config->{api_timeout} ? $config->{api_timeout} : 10;
56             }
57              
58             sub _g_captcha_config {
59 8     8   20 my ($self) = @_;
60 8 50 33     200 return unless ($self->form && $self->form->ctx && $self->form->ctx->config);
      33        
61 0         0 return $self->form->ctx->config->{$self->config_key};
62             }
63              
64             sub _build__nocaptcha {
65 5     5   15 my ($self) = @_;
66 5         166 return Captcha::noCAPTCHA->new({
67             api_url => $self->api_url,
68             api_timeout => $self->api_timeout,
69             site_key => $self->site_key,
70             secret_key => $self->secret_key,
71             theme => $self->theme,
72             noscript => $self->noscript,
73             });
74             }
75              
76             sub validate {
77 3     3 1 4393 my ($self) = @_;
78              
79 3         100 my $cap = $self->_nocaptcha;
80              
81 3         15 my $success = $cap->verify( $self->value, $self->remote_address );
82              
83 3 100       451 if (not defined $success) {
    100          
84 1         36 $self->add_error($self->g_captcha_failure_message);
85 1         2630 return;
86             } elsif (!$success) {
87 1         34 $self->add_error($self->g_captcha_message);
88             }
89              
90 2         759 return;
91             }
92              
93             1;
94              
95             =head1 NAME
96              
97             HTML::FormHandlerX::Field::noCAPTCHA - Google's noCAPTCHA reCAPTCHA for HTML::FormHandler
98              
99             =head1 SYNOPSIS
100              
101             The following is example usage.
102              
103             In your L<HTML::FormHandler> subclass, "YourApp::HTML::Forms::YourForm":
104              
105             has_field 'nocaptcha' => (
106             type=>'noCAPTCHA',
107             site_key=>'[YOUR SITE KEY]',
108             secret_key=>'[YOUR SECRET KEY]',
109             );
110              
111             Example L<Catalyst> controller:
112              
113             my $form = YourApp::HTML::Forms::YourForm->new({ctx => $c});
114             my $params = $c->request->body_parameters;
115             if($form->process($c->req->body_parameters) {
116             ## Do something with the form.
117             } else {
118             ## Redisplay form and ask to try again.
119             }
120              
121             Example L<Catalyst> config:
122              
123             __PACKAGE__->config(
124             'HTML::FormHandlerX::Field::noCAPTCHA' => {
125             site_key => '[YOUR SITE KEY]',
126             secret_key => '[YOUR SECRET KEY]',
127             },
128             );
129              
130             =head1 FIELD OPTIONS
131              
132             Support for the following field options, over what is inherited from
133             L<HTML::FormHandler::Field>
134              
135             =head2 site_key
136              
137             Required. The site key you get when you create an account on L<https://www.google.com/recaptcha/>
138              
139             =head2 secret_key
140              
141             Required. The secret key you get when you create an account on L<https://www.google.com/recaptcha/>
142              
143             =head2 theme
144              
145             Optional. The color theme of the widget. Options are 'light ' or 'dark' (Default: light)
146              
147             =head2 noscript
148              
149             Optional. When true, includes the <noscript> markup in the rendered html. (Default: false)
150              
151             =head2 remote_address
152              
153             Optional. The user's IP address. Google states this is optional. If you are using
154             catalyst and pass the context to the form, noCAPTCHA will use it by default.
155              
156             =head2 api_url
157              
158             Optional. URL to the Google API. Defaults to https://www.google.com/recaptcha/api/siteverify
159              
160             =head2 api_timeout
161              
162             Optional. Seconds to wait for Google API to respond. Default is 10 seconds.
163              
164             =head2 g_captcha_message
165              
166             Optional. Message to display if user answers captcha incorrectly.
167             Default is "You've failed to prove your Humanity!"
168              
169             =head2 g_captcha_failure_message
170              
171             Optional. Message to display if there was an issue with Google's API response.
172             Default is "We've had trouble processing your request, please try again."
173              
174             =head2 config_key
175              
176             Optional. When passing catalyst context to L<HTML::FormHandler>, uses this values
177             as the key to lookup configurations for this package.
178             Default is HTML::FormHandlerX::Field::noCAPTCHA
179              
180             =head1 SEE ALSO
181              
182             The following modules or resources may be of interest.
183              
184             L<HTML::FormHandler>
185             L<Captcha::noCAPTCHA>
186              
187             =head1 AUTHOR
188              
189             Chuck Larson C<< <clarson@cpan.org> >>
190              
191             =head1 COPYRIGHT & LICENSE
192              
193             Copyright 2017, Chuck Larson C<< <chuck+github@endcapsoftwware.com> >>
194              
195             This projects work sponsored by End Cap Software, LLC.
196             L<http://www.endcapsoftware.com>
197              
198             Original work by John Napiorkowski C<< <jjnapiork@cpan.org> >>
199              
200             This program is free software; you can redistribute it and/or modify
201             it under the same terms as Perl itself.
202              
203             =cut