diff --git a/lib/PostText/Controller/Page.pm b/lib/PostText/Controller/Page.pm index d457a31..58cf99c 100644 --- a/lib/PostText/Controller/Page.pm +++ b/lib/PostText/Controller/Page.pm @@ -20,8 +20,15 @@ sub captcha($self) { if ($v && $v->has_data) { $v->required('answer')->num(1, 9); $v->required('number')->size(1, 4); + $v->csrf_protect; - if ($v->has_error) { + if ($v->has_error('csrf_token')) { + $self->stash( + status => 403, + error => 'Something went wrong, please try again. 🥺' + ) + } + elsif ($v->has_error) { $self->stash(status => 400) } else { diff --git a/t/post.t b/t/post.t index fac43b4..67898cb 100644 --- a/t/post.t +++ b/t/post.t @@ -44,6 +44,11 @@ $t->get_ok('/human/remark/post/1')->status_is(302) ->header_like(Location => qr/captcha/); # Do CAPTCHA +$t->get_ok($bump_thread_url); + +$good_captcha{'csrf_token'} = + $t->tx->res->dom->at('input[name="csrf_token"]')->val; + $t->post_ok($bump_thread_url, form => \%good_captcha) ->status_is(302) ->header_like(Location => qr{human/thread/bump/1}); @@ -51,8 +56,6 @@ $t->post_ok($bump_thread_url, form => \%good_captcha) $t->ua->max_redirects(1); subtest 'Post new thread', sub { - my $csrf_token; - # GET $t->get_ok('/human/thread/post')->status_is(200) ->element_exists('form input[name="author"]' ) @@ -121,10 +124,25 @@ subtest 'Post new remark', sub { ->element_exists('form button[type="submit"]' ) ->text_like(h2 => qr/Remark on Thread #/); + # No CSRF token + $t->post_ok('/human/remark/post/1', form => \%valid_remark) + ->status_is(403) + ->text_like(p => qr/Something went wrong/); + + $t->get_ok('/human/remark/post/1'); + + $valid_remark{'csrf_token'} = + $t->tx->res->dom->at('input[name="csrf_token"]')->val; + $t->post_ok('/human/remark/post/1', form => \%valid_remark) ->status_is(200) ->text_like(h2 => qr/Thread #1/); + $t->get_ok('/human/remark/post/1'); + + $invalid_remark{'csrf_token'} = + $t->tx->res->dom->at('input[name="csrf_token"]')->val; + $t->post_ok('/human/remark/post/1', form => \%invalid_remark) ->status_is(400) ->text_like(p => qr/Must be between/);