From 4584a681e0e57453da587d92877d94e20f9b9269 Mon Sep 17 00:00:00 2001 From: swaggboi Date: Sat, 5 Aug 2023 15:22:02 -0400 Subject: [PATCH] Finish the CAPTCHA stuff --- README.md | 3 +- cpanfile | 1 + lib/PostText.pm | 4 +- lib/PostText/Controller/Page.pm | 3 +- t/human.t | 104 ++++++++++++++++++++++++++++++++ t/remark.t | 16 ----- t/thread.t | 40 ------------ templates/page/captcha.html.ep | 4 +- 8 files changed, 112 insertions(+), 63 deletions(-) create mode 100644 t/human.t diff --git a/README.md b/README.md index 811fb15..3c4bca4 100644 --- a/README.md +++ b/README.md @@ -62,8 +62,7 @@ tests locally: ## TODOs 1. Post preview -1. There was something else but I forget... -1. CAPTCHA +1. Need to check b64 input for the return_url param probably 1. "All new posts flagged" mode (require approval for new posts) 1. Tests for mod-only user? diff --git a/cpanfile b/cpanfile index 5180947..885e6e9 100644 --- a/cpanfile +++ b/cpanfile @@ -9,3 +9,4 @@ requires 'CSS::Minifier::XS'; requires 'Text::Markdown'; requires 'HTML::Restrict'; requires 'IO::Socket::SSL'; +requires 'Roman::Unicode'; diff --git a/lib/PostText.pm b/lib/PostText.pm index 471e0a6..020db06 100644 --- a/lib/PostText.pm +++ b/lib/PostText.pm @@ -135,7 +135,7 @@ sub startup($self) { $r->get('/rules')->to('page#rules')->name('rules_page'); - $r->any('/captcha/:return_url') + $r->any([qw{GET POST}], '/captcha/:return_url') ->to('page#captcha') ->name('captcha_page'); @@ -183,7 +183,7 @@ sub startup($self) { ->to('remark#by_id') ->name('single_remark'); - $remark->get('/flag/:remark_id', [remark_id => qr/\d+/]) + $human_remark->get('/flag/:remark_id', [remark_id => qr/\d+/]) ->to('remark#flag') ->name('flag_remark'); diff --git a/lib/PostText/Controller/Page.pm b/lib/PostText/Controller/Page.pm index 13f8994..d08cf7b 100644 --- a/lib/PostText/Controller/Page.pm +++ b/lib/PostText/Controller/Page.pm @@ -33,7 +33,8 @@ sub captcha($self) { } else { $self->stash( - error => 'Sounds like something a robot would say...' + status => 400, + error => 'Sounds like something a robot would say...' ) } } diff --git a/t/human.t b/t/human.t new file mode 100644 index 0000000..86bf1d5 --- /dev/null +++ b/t/human.t @@ -0,0 +1,104 @@ +use Mojo::Base -strict; +use Test::More; +use Test::Mojo; + +my $t = Test::Mojo->new('PostText'); +my %good_human = (answer => 1, number => 'Ⅰ'); +my %bad_bot = (answer => 2, number => 'Ⅰ'); +my %invalid_captcha = (answer => 'a', number => 'Ⅰ'); +my $flag_thread_url = + '/captcha/H4sIABSTzmQAA8soKSmw0tfPyU9OzMnILy6xMjYwMNDPKM1NzNMvyShKTUzRT8tJTNc3BABRx5B2%0AKQAAAA==%0A'; +my $bump_thread_url = + '/captcha/H4sIAImTzmQAA8soKSmw0tfPyU9OzMnILy6xMjYwMNDPKM1NzNMvyShKTUzRTyrNLdA3BAD5ek7T%0AKQAAAA==%0A'; +my $flag_remark_url = + '/captcha/H4sIAAKazmQAA8soKSmw0tfPyU9OzMnILy6xMjYwMNDPKM1NzNMvSs1NLMrWT8tJTNc3BAAN5VIw%0AKQAAAA==%0A'; + +subtest 'Bumping thread', sub { + $t->get_ok('/thread/list')->status_is(200) + ->element_exists('a[href*="bump"]') + ->text_like(h2 => qr/Threads List/); + + $t->get_ok('/thread/single/1')->status_is(200) + ->element_exists('a[href*="bump"]') + ->text_like(h2 => qr/Thread #1/); + + $t->get_ok('/human/thread/bump/1')->status_is(302) + ->header_like(Location => qr/captcha/); + + # Bad CAPTCHA + $t->post_ok($bump_thread_url, form => \%bad_bot) + ->status_is(400) + ->element_exists('p[class="stash-with-error"]') + ->text_like(p => qr/Sounds like something a robot would say/); + + $t->post_ok($bump_thread_url, form => \%invalid_captcha) + ->status_is(400) + ->element_exists('p[class="field-with-error"]') + ->text_like(p => qr/Should be a single number/); + + # Solved CAPTCHA + $t->post_ok($bump_thread_url, form => \%good_human) + ->status_is(302) + ->header_like(Location => qr{human/thread/bump/1}); + + $t->reset_session; +}; + +subtest 'Flagging thread', sub { + $t->get_ok('/thread/list')->status_is(200) + ->element_exists('a[href*="flag"]') + ->text_like(h2 => qr/Threads List/); + + $t->get_ok('/thread/single/1')->status_is(200) + ->element_exists('a[href*="flag"]') + ->text_like(h2 => qr/Thread #1/); + + $t->get_ok('/human/thread/flag/1')->status_is(302) + ->header_like(Location => qr/captcha/); + + # Bad CAPTCHA + $t->post_ok($flag_thread_url, form => \%bad_bot) + ->status_is(400) + ->element_exists('p[class="stash-with-error"]') + ->text_like(p => qr/Sounds like something a robot would say/); + + $t->post_ok($flag_thread_url, form => \%invalid_captcha) + ->status_is(400) + ->element_exists('p[class="field-with-error"]') + ->text_like(p => qr/Should be a single number/); + + # Solved CAPTCHA + $t->post_ok($flag_thread_url, form => \%good_human) + ->status_is(302) + ->header_like(Location => qr{human/thread/flag/1}); + + $t->reset_session; +}; + +subtest 'Flagging remark', sub { + $t->get_ok('/remark/single/1')->status_is(200) + ->element_exists('a[href*="flag"]') + ->text_like(h2 => qr/Remark #1/); + + $t->get_ok('/human/remark/flag/1')->status_is(302) + ->header_like(Location => qr/captcha/); + + # Bad CAPTCHA + $t->post_ok($flag_remark_url, form => \%bad_bot) + ->status_is(400) + ->element_exists('p[class="stash-with-error"]') + ->text_like(p => qr/Sounds like something a robot would say/); + + $t->post_ok($flag_remark_url, form => \%invalid_captcha) + ->status_is(400) + ->element_exists('p[class="field-with-error"]') + ->text_like(p => qr/Should be a single number/); + + # Solved CAPTCHA + $t->post_ok($flag_remark_url, form => \%good_human) + ->status_is(302) + ->header_like(Location => qr{human/remark/flag/1}); +}; + + +done_testing; diff --git a/t/remark.t b/t/remark.t index 492f645..3473f33 100644 --- a/t/remark.t +++ b/t/remark.t @@ -61,20 +61,4 @@ subtest 'Post new remark', sub { ->text_like(p => qr/Must be between/); }; -subtest 'Flagging remark', sub { - $t->get_ok('/remark/single/1')->status_is(200) - ->element_exists('a[href*="flag"]') - ->text_like(h2 => qr/Remark #1/); - - $t->get_ok('/human/remark/flag/1')->status_is(302) - ->header_like(Location => qr/captcha/); - - # Solved CAPTCHA - $tx->req->cookies({is_human => 1}); - - $t->get_ok('/human/thread/flag/1')->status_is(200) - ->element_exists('p[class="stash-with-info"]') - ->text_like(p => qr/Thread #1 has been flagged/); -}; - done_testing; diff --git a/t/thread.t b/t/thread.t index 9dcb01f..7debe82 100644 --- a/t/thread.t +++ b/t/thread.t @@ -87,44 +87,4 @@ subtest 'Post new thread', sub { ->text_like(h2 => qr/Thread #\d+/); }; -subtest 'Bumping thread', sub { - $t->get_ok('/thread/list')->status_is(200) - ->element_exists('a[href*="bump"]') - ->text_like(h2 => qr/Threads List/); - - $t->get_ok('/thread/single/1')->status_is(200) - ->element_exists('a[href*="bump"]') - ->text_like(h2 => qr/Thread #1/); - - $t->get_ok('/human/thread/bump/1')->status_is(302) - ->header_like(Location => qr/captcha/); - - # Solved CAPTCHA - $tx->req->cookies({is_human => 1}); - - $t->get_ok('/human/thread/bump/1')->status_is(200) - ->element_exists('p[class="stash-with-info"]') - ->text_like(p => qr/Thread #1 has been bumped/); -}; - -subtest 'Flagging thread', sub { - $t->get_ok('/thread/list')->status_is(200) - ->element_exists('a[href*="flag"]') - ->text_like(h2 => qr/Threads List/); - - $t->get_ok('/thread/single/1')->status_is(200) - ->element_exists('a[href*="flag"]') - ->text_like(h2 => qr/Thread #1/); - - $t->get_ok('/human/thread/flag/1')->status_is(302) - ->header_like(Location => qr/captcha/); - - # Solved CAPTCHA - $tx->req->cookies({is_human => 1}); - - $t->get_ok('/human/thread/flag/1')->status_is(200) - ->element_exists('p[class="stash-with-info"]') - ->text_like(p => qr/Thread #1 has been flagged/); -}; - done_testing; diff --git a/templates/page/captcha.html.ep b/templates/page/captcha.html.ep index 2aff6e3..8a9010b 100644 --- a/templates/page/captcha.html.ep +++ b/templates/page/captcha.html.ep @@ -13,8 +13,8 @@
<% if (my $error = validation->error('answer')) { =%> -

Must be between <%= $error->[2] %> - and <%= $error->[3] %> characters.

+

Should be a single number between + <%= $error->[2] %> and <%= $error->[3] %>.

<% } =%> <%= label_for answer => "What roman numeral is this?: $roman_numeral" %> <%= text_field 'answer', (