Validate input

This commit is contained in:
swagg boi 2022-01-08 21:21:22 -05:00
parent 84182fe25b
commit e4aad2ccbd
4 changed files with 58 additions and 38 deletions

View file

@ -49,6 +49,6 @@ Add the `-v` option for more verbose output
## TODOs
1. Input validation
1. More tests
1. /spam route would be interesting
1. Include the total number of visitors or messages

View file

@ -132,7 +132,7 @@ h1#top {
}
.error {
border-style: solid;
border-style: dashed;
border-color: red;
color: red;
padding: 1em;
@ -140,6 +140,12 @@ h1#top {
margin-bottom: 1em;
}
.field-with-error {
border-style: dotted;
border-color: red;
padding-left: 1em;
}
@media screen and (max-width: 1023px) {
.inner {
max-width: 95%;

View file

@ -46,6 +46,9 @@ under sub ($c) {
$c->session(expiration => 604800);
$c->stash(status => 403)
if $c->flash('error') eq 'This message was flagged as spam';
1;
};
@ -64,7 +67,9 @@ get '/' => sub ($c) {
} => 'index';
any [qw{GET POST}], '/sign' => sub ($c) {
if ($c->req->method() eq 'POST') {
my $v = $c->validation();
if ($c->req->method eq 'POST' && $v->has_data) {
my $name = $c->param('name') || 'Anonymous';
my $url = $c->param('url');
my $message = $c->param('message');
@ -73,37 +78,37 @@ any [qw{GET POST}], '/sign' => sub ($c) {
$message =~ /$RE{URI}{HTTP}{-scheme => qr<https?>}/ ? 1 :
0;
if ($message) {
$v->required('name' )->size(1, 63);
$v->required('message')->size(2, 2000);
$v->optional('url', 'not_empty')->size(1, 255)
->like(qr/$RE{URI}{HTTP}{-scheme => qr<https?>}/);
unless ($v->has_error) {
$c->message->create_post($name, $message, $url, $spam);
$c->flash(error => 'This message was flagged as spam') if $spam;
$c->redirect_to('index');
}
else {
$c->flash(error => 'Message cannot be blank');
$c->redirect_to('sign');
}
}
else {
# Try to randomize things for the CAPTCHA challenge. The
# string 'false' actually evaluates to true so this is an
# attempt to confuse a (hypothetical) bot that would try to
# select what it thinks is the right answer
my @answers = shuffle(0, 'false', undef);
my $right_answer_label = 'I\'m ready to sign (choose this one)';
my @wrong_answer_labels = shuffle(
'I don\'t want to sign (wrong answer)',
'This is spam/I\'m a bot, do not sign'
);
$c->stash(
answers => \@answers,
right_answer_label => $right_answer_label,
wrong_answer_labels => \@wrong_answer_labels
);
# Try to randomize things for the CAPTCHA challenge. The
# string 'false' actually evaluates to true so this is an
# attempt to confuse a (hypothetical) bot that would try to
# select what it thinks is the right answer
my @answers = shuffle(0, 'false', undef);
my $right_answer_label = 'I\'m ready to sign (choose this one)';
my @wrong_answer_labels = shuffle(
'I don\'t want to sign (wrong answer)',
'This is spam/I\'m a bot, do not sign'
);
$c->render();
}
$c->stash(
answers => \@answers,
right_answer_label => $right_answer_label,
wrong_answer_labels => \@wrong_answer_labels
);
$c->render();
};
# Send it

View file

@ -4,27 +4,36 @@
<form method="post">
<div class="name field">
<%= label_for name => 'Name' %>
<%= input_tag name =>'Anonymous', maxlength => 63, minlength => 1 %>
<%= text_field name =>'Anonymous', maxlength => 63, minlength => 1 %>
</div>
<div class="url field">
<%= label_for url => 'Homepage URL' %>
<%= input_tag 'url', maxlength => 255 %>
<%= text_field 'url', maxlength => 255 %>
<% if (my $error = validation->error('url')) { =%>
<p class="field-with-error">URL does not appear to be
<%= link_to 'RFC 2616',
'https://datatracker.ietf.org/doc/html/rfc2616/#section-3.2.2' %>
compliant.</p>
<% } =%>
</div>
<div class="message field">
<%= label_for message => 'Message' %>
<textarea
name="message"
maxlength="2000"
minlength="2"
required="true"
rows="6"></textarea>
<%= label_for message => 'Message' %>
<%= text_area 'message',
maxlength => 2000,
minlength => 2,
required => 'true',
rows => 6 %>
<% if (my $error = validation->error('message')) { =%>
<p class="field-with-error">Message must be less than 2,000
characters and cannot be blank.</p>
<% } =%>
</div>
<h3>SwaggCAPTCHA™</h3>
<div class="captcha field">
<% for my $answer (@$answers) { =%>
<%= radio_button answer => $answer %>
<%= label_for answer =>
$answer ? $right_answer_label : pop @$wrong_answer_labels %>
<%= radio_button answer => $answer %>
<%= label_for answer =>
$answer ? $right_answer_label : pop @$wrong_answer_labels %>
<% } =%>
</div>
<%= submit_button 'Sign it', class => 'win95button' %>