Sanitize HTML in body; enforce NOT NULL on body; template clean-up
This commit is contained in:
parent
5e857b9426
commit
ab0f53ba26
|
@ -58,9 +58,10 @@ Run the tests locally (against development environment):
|
||||||
|
|
||||||
## TODOs
|
## TODOs
|
||||||
|
|
||||||
1. Use something like HTML::Restrict on thread/remark body
|
|
||||||
1. CSS
|
1. CSS
|
||||||
1. "All new posts flagged" mode (require approval for new posts)
|
1. "All new posts flagged" mode (require approval for new posts)
|
||||||
|
1. Tests for mod-only user?
|
||||||
|
1. Check input validation
|
||||||
|
|
||||||
## Crazy future ideas
|
## Crazy future ideas
|
||||||
|
|
||||||
|
|
1
cpanfile
1
cpanfile
|
@ -9,3 +9,4 @@ requires 'Date::Format';
|
||||||
requires 'XML::RSS';
|
requires 'XML::RSS';
|
||||||
requires 'CSS::Minifier::XS';
|
requires 'CSS::Minifier::XS';
|
||||||
requires 'Text::Markdown';
|
requires 'Text::Markdown';
|
||||||
|
requires 'HTML::Restrict';
|
||||||
|
|
|
@ -6,6 +6,7 @@ use Mojo::Base 'Mojolicious', -signatures;
|
||||||
use Mojo::Pg;
|
use Mojo::Pg;
|
||||||
use Crypt::Passphrase;
|
use Crypt::Passphrase;
|
||||||
use Text::Markdown qw{markdown};
|
use Text::Markdown qw{markdown};
|
||||||
|
use HTML::Restrict;
|
||||||
|
|
||||||
# The local libs
|
# The local libs
|
||||||
use PostText::Model::Thread;
|
use PostText::Model::Thread;
|
||||||
|
@ -29,12 +30,22 @@ sub startup($self) {
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$self->helper(hr => sub ($c) {
|
||||||
|
state $hr = HTML::Restrict->new(strip_enclosed_content => [])
|
||||||
|
});
|
||||||
|
|
||||||
$self->helper(thread => sub ($c) {
|
$self->helper(thread => sub ($c) {
|
||||||
state $thread = PostText::Model::Thread->new(pg => $c->pg)
|
state $thread = PostText::Model::Thread->new(
|
||||||
|
pg => $c->pg,
|
||||||
|
hr => $c->hr
|
||||||
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
$self->helper(remark => sub ($c) {
|
$self->helper(remark => sub ($c) {
|
||||||
state $remark = PostText::Model::Remark->new(pg => $c->pg)
|
state $remark = PostText::Model::Remark->new(
|
||||||
|
pg => $c->pg,
|
||||||
|
hr => $c->hr
|
||||||
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
$self->helper(moderator => sub ($c) {
|
$self->helper(moderator => sub ($c) {
|
||||||
|
@ -70,7 +81,7 @@ sub startup($self) {
|
||||||
# Finish configuring some things
|
# Finish configuring some things
|
||||||
$self->secrets($self->config->{'secrets'}) || die $@;
|
$self->secrets($self->config->{'secrets'}) || die $@;
|
||||||
|
|
||||||
$self->pg->migrations->from_dir('migrations')->migrate(11);
|
$self->pg->migrations->from_dir('migrations')->migrate(12);
|
||||||
|
|
||||||
if (my $threads_per_page = $self->config->{'threads_per_page'}) {
|
if (my $threads_per_page = $self->config->{'threads_per_page'}) {
|
||||||
$self->thread->per_page($threads_per_page)
|
$self->thread->per_page($threads_per_page)
|
||||||
|
|
|
@ -2,7 +2,7 @@ package PostText::Model::Remark;
|
||||||
|
|
||||||
use Mojo::Base -base, -signatures;
|
use Mojo::Base -base, -signatures;
|
||||||
|
|
||||||
has 'pg';
|
has [qw{pg hr}];
|
||||||
|
|
||||||
has per_page => 5;
|
has per_page => 5;
|
||||||
|
|
||||||
|
@ -28,7 +28,8 @@ sub by_page_for($self, $thread_id, $this_page = 1) {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub create($self, $thread_id, $author, $body, $hidden = 0, $flagged = 0) {
|
sub create($self, $thread_id, $author, $body, $hidden = 0, $flagged = 0) {
|
||||||
my @data = ($thread_id, $author, $body, $hidden, $flagged);
|
my $clean_body = $self->hr->process($body);
|
||||||
|
my @data = ($thread_id, $author, $clean_body, $hidden, $flagged);
|
||||||
|
|
||||||
$self->pg->db->query(<<~'END_SQL', @data);
|
$self->pg->db->query(<<~'END_SQL', @data);
|
||||||
INSERT INTO remarks (
|
INSERT INTO remarks (
|
||||||
|
|
|
@ -2,14 +2,15 @@ package PostText::Model::Thread;
|
||||||
|
|
||||||
use Mojo::Base -base, -signatures;
|
use Mojo::Base -base, -signatures;
|
||||||
|
|
||||||
has 'pg';
|
has [qw{pg hr}];
|
||||||
|
|
||||||
has per_page => 5;
|
has per_page => 5;
|
||||||
|
|
||||||
has date_format => 'Dy, FMDD Mon YYYY HH24:MI:SS TZ';
|
has date_format => 'Dy, FMDD Mon YYYY HH24:MI:SS TZ';
|
||||||
|
|
||||||
sub create($self, $author, $title, $body, $hidden = 0, $flagged = 0) {
|
sub create($self, $author, $title, $body, $hidden = 0, $flagged = 0) {
|
||||||
my @data = ($author, $title, $body, $hidden, $flagged);
|
my $clean_body = $self->hr->process($body);
|
||||||
|
my @data = ($author, $title, $clean_body, $hidden, $flagged);
|
||||||
|
|
||||||
$self->pg->db->query(<<~'END_SQL', @data)->hash->{'thread_id'};
|
$self->pg->db->query(<<~'END_SQL', @data)->hash->{'thread_id'};
|
||||||
INSERT INTO threads (
|
INSERT INTO threads (
|
||||||
|
|
7
migrations/12/down.sql
Normal file
7
migrations/12/down.sql
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
ALTER TABLE threads
|
||||||
|
ALTER COLUMN thread_body
|
||||||
|
DROP NOT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE remarks
|
||||||
|
ALTER COLUMN remark_body
|
||||||
|
DROP NOT NULL;
|
9
migrations/12/up.sql
Normal file
9
migrations/12/up.sql
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
-- Input validation may fail for body if user submits only an HTML tag
|
||||||
|
|
||||||
|
ALTER TABLE threads
|
||||||
|
ALTER COLUMN thread_body
|
||||||
|
SET NOT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE remarks
|
||||||
|
ALTER COLUMN remark_body
|
||||||
|
SET NOT NULL;
|
|
@ -3,13 +3,13 @@
|
||||||
<h2><%= title %></h2>
|
<h2><%= title %></h2>
|
||||||
<div class="about body">
|
<div class="about body">
|
||||||
<p>Post::Text is a <a href="">textboard</a> a bit like 2channel. You
|
<p>Post::Text is a <a href="">textboard</a> a bit like 2channel. You
|
||||||
can post whatever you want anonymously just please mind the
|
can post whatever you want anonymously just please mind the <%=
|
||||||
<%= link_to rules => 'rules_page' %>. Markdown is supported for
|
link_to rules => 'rules_page' %>. Markdown is supported for
|
||||||
formatting posts using the
|
formatting posts using the <a
|
||||||
<a href="https://daringfireball.net/projects/markdown/syntax">
|
href="https://daringfireball.net/projects/markdown/syntax">
|
||||||
original implementation from The Daring Fireball</a>. For
|
original implementation from The Daring Fireball</a>. For example,
|
||||||
example, back-ticks are for <em>inline code</em> while
|
back-ticks are for <em>inline code</em> while indentation should
|
||||||
indentation should be used if you want an entire code bock:</p>
|
be used if you want an entire code bock:</p>
|
||||||
<pre><code>
|
<pre><code>
|
||||||
This is `inline_code()` and so is ```this()```. This is incorrect:
|
This is `inline_code()` and so is ```this()```. This is incorrect:
|
||||||
|
|
||||||
|
@ -24,9 +24,10 @@ This is correct for a multi-line code block:
|
||||||
if (true) {
|
if (true) {
|
||||||
do_stuff();
|
do_stuff();
|
||||||
}
|
}
|
||||||
|
|
||||||
You can use an actual tab character or four spaces to indent.
|
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
<p>You can use an actual tab character or four spaces to indent.
|
||||||
|
<strong>Only Markdown is supported, HTML will be filtered
|
||||||
|
out.</strong></p>
|
||||||
<p>There is a button for users to 'flag' a post for review by a
|
<p>There is a button for users to 'flag' a post for review by a
|
||||||
moderator. If you need further assistance you can reach out to the
|
moderator. If you need further assistance you can reach out to the
|
||||||
<a href="mailto:swaggboi@slackware.uk">webmaster</a>. There is
|
<a href="mailto:swaggboi@slackware.uk">webmaster</a>. There is
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
<nav class="id">#<%= $remark->{'id'} %></nav>
|
<nav class="id">#<%= $remark->{'id'} %></nav>
|
||||||
<h4 class="date"><%= $remark->{'date'} %></h4>
|
<h4 class="date"><%= $remark->{'date'} %></h4>
|
||||||
<h5 class="author"><%= $remark->{'author'} %></h5>
|
<h5 class="author"><%= $remark->{'author'} %></h5>
|
||||||
<div class="body"><%== markdown $remark->{'body'} %></div>
|
<div class="body">
|
||||||
|
<%== markdown $remark->{'body'} =%>
|
||||||
|
</div>
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
<nav>
|
<nav>
|
||||||
|
|
|
@ -37,7 +37,9 @@
|
||||||
<h3 class="title"><%= $thread->{'title'} %></h3>
|
<h3 class="title"><%= $thread->{'title'} %></h3>
|
||||||
<h4 class="date"><%= $thread->{'date'} %></h4>
|
<h4 class="date"><%= $thread->{'date'} %></h4>
|
||||||
<h5 class="author"><%= $thread->{'author'} %></h5>
|
<h5 class="author"><%= $thread->{'author'} %></h5>
|
||||||
<div class="body"><%== markdown $thread->{'body'} %></div>
|
<div class="body">
|
||||||
|
<%== markdown $thread->{'body'} =%>
|
||||||
|
</div>
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
<% if (my $last_remark_id = $last_remark->{'id'}) { =%>
|
<% if (my $last_remark_id = $last_remark->{'id'}) { =%>
|
||||||
|
@ -50,7 +52,9 @@
|
||||||
</nav>
|
</nav>
|
||||||
<h4 class="date"><%= $last_remark->{'date'} %></h4>
|
<h4 class="date"><%= $last_remark->{'date'} %></h4>
|
||||||
<h5 class="author"><%= $last_remark->{'author'} %></h5>
|
<h5 class="author"><%= $last_remark->{'author'} %></h5>
|
||||||
<div class="body"><%== markdown $last_remark->{'body'} %></div>
|
<div class="body">
|
||||||
|
<%== markdown $last_remark->{'body'} =%>
|
||||||
|
</div>
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
<% } =%>
|
<% } =%>
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
<h3 class="title"><%= $thread->{'title'} %></h3>
|
<h3 class="title"><%= $thread->{'title'} %></h3>
|
||||||
<h4 class="date"><%= $thread->{'date'} %></h4>
|
<h4 class="date"><%= $thread->{'date'} %></h4>
|
||||||
<h5 class="author"><%= $thread->{'author'} %></h5>
|
<h5 class="author"><%= $thread->{'author'} %></h5>
|
||||||
<div class="body"><%== markdown $thread->{'body'} %></div>
|
<div class="body">
|
||||||
|
<%== markdown $thread->{'body'} =%>
|
||||||
|
</div>
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
<nav>
|
<nav>
|
||||||
|
@ -32,7 +34,9 @@
|
||||||
</nav>
|
</nav>
|
||||||
<h4 class="date"><%= $remark->{'date'} %></h4>
|
<h4 class="date"><%= $remark->{'date'} %></h4>
|
||||||
<h5 class="author"><%= $remark->{'author'} %></h5>
|
<h5 class="author"><%= $remark->{'author'} %></h5>
|
||||||
<div class="body"><%== markdown $remark->{'body'} %></div>
|
<div class="body">
|
||||||
|
<%== markdown $remark->{'body'} =%>
|
||||||
|
</div>
|
||||||
<nav class="flag">
|
<nav class="flag">
|
||||||
<%= link_to Flag => flag_remark => {remark_id => $remark->{'id'}} %>
|
<%= link_to Flag => flag_remark => {remark_id => $remark->{'id'}} %>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
|
@ -15,7 +15,9 @@
|
||||||
</h3>
|
</h3>
|
||||||
<h4 class="date"><%= $thread->{'date'} %></h4>
|
<h4 class="date"><%= $thread->{'date'} %></h4>
|
||||||
<h5 class="author"><%= $thread->{'author'} %></h5>
|
<h5 class="author"><%= $thread->{'author'} %></h5>
|
||||||
<div class="body"><%== markdown truncate_text $thread->{'body'} %></div>
|
<div class="body">
|
||||||
|
<%== markdown truncate_text $thread->{'body'} =%>
|
||||||
|
</div>
|
||||||
<nav>
|
<nav>
|
||||||
<%= link_to Remark => post_remark => {thread_id => $thread->{'id'}} %>
|
<%= link_to Remark => post_remark => {thread_id => $thread->{'id'}} %>
|
||||||
<%= link_to url_for(single_thread => {thread_id => $thread->{'id'}})
|
<%= link_to url_for(single_thread => {thread_id => $thread->{'id'}})
|
||||||
|
|
Loading…
Reference in a new issue