Browse Source

implement post validation

main
ghost 12 months ago
parent
commit
d4e450b6af
  1. 9
      .env
  2. 4
      config/services.yaml
  3. 8
      public/css/default.css
  4. 3
      src/Controller/ModuleController.php
  5. 133
      src/Controller/RoomController.php
  6. 5
      templates/default/module/post.html.twig
  7. 2
      templates/default/room/index.html.twig

9
.env

@ -23,6 +23,10 @@ APP_VERSION=1.0.0 @@ -23,6 +23,10 @@ APP_VERSION=1.0.0
APP_NAME=KevaChat
# Connect memcached
APP_MEMCACHED_HOST=127.0.0.1
APP_MEMCACHED_PORT=11211
# Connect kevacoin
APP_KEVACOIN_PROTOCOL=http
@ -59,5 +63,8 @@ APP_ADD_POST_REMOTE_IP_DELAY=60 @@ -59,5 +63,8 @@ APP_ADD_POST_REMOTE_IP_DELAY=60
# Skip access limits for following IPs separated by |
APP_ADD_POST_REMOTE_IP_MODERATORS=
# Skip access limits for banned IPs separated by |
APP_ADD_POST_REMOTE_IP_DENIED=
# Post content rules (for kevacoin value)
APP_ADD_POST_VALUE_REGEX=/[\w]{2,3072}/
APP_ADD_POST_VALUE_REGEX=/^[\w\s]{2,3072}$/ui

4
config/services.yaml

@ -6,7 +6,8 @@ @@ -6,7 +6,8 @@
parameters:
app.version: '%env(APP_VERSION)%'
app.name: '%env(APP_NAME)%'
app.memcached.host: '%env(APP_MEMCACHED_HOST)%'
app.memcached.port: '%env(APP_MEMCACHED_PORT)%'
app.kevacoin.protocol: '%env(APP_KEVACOIN_PROTOCOL)%'
app.kevacoin.host: '%env(APP_KEVACOIN_HOST)%'
app.kevacoin.port: '%env(APP_KEVACOIN_PORT)%'
@ -22,6 +23,7 @@ parameters: @@ -22,6 +23,7 @@ parameters:
app.add.post.remote.ip.regex: '%env(APP_ADD_POST_REMOTE_IP_REGEX)%'
app.add.post.remote.ip.delay: '%env(APP_ADD_POST_REMOTE_IP_DELAY)%'
app.add.post.remote.ip.moderators: '%env(APP_ADD_POST_REMOTE_IP_MODERATORS)%'
app.add.post.remote.ip.denied: '%env(APP_ADD_POST_REMOTE_IP_DENIED)%'
app.add.post.value.regex: '%env(APP_ADD_POST_VALUE_REGEX)%'
services:

8
public/css/default.css

@ -147,3 +147,11 @@ footer > form > button @@ -147,3 +147,11 @@ footer > form > button
float: right;
padding: 2px 8px;
}
footer > form > output
{
color: #ff6363;
display: block;
font-weight: bolder;
margin-bottom: 16px;
}

3
src/Controller/ModuleController.php

@ -156,8 +156,9 @@ class ModuleController extends AbstractController @@ -156,8 +156,9 @@ class ModuleController extends AbstractController
[
'enabled' => in_array($request->get('namespace'), $public),
'namespace' => $request->get('namespace'),
'message' => $message,
'user' => $request->get('user'),
'error' => $request->get('error'),
'message' => $message,
'ip' => $request->getClientIp()
]
);

133
src/Controller/RoomController.php

@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Response;
@ -165,9 +166,27 @@ class RoomController extends AbstractController @@ -165,9 +166,27 @@ class RoomController extends AbstractController
]
)]
public function post(
Request $request
Request $request,
TranslatorInterface $translator
): Response
{
// Connect memcached
$memcached = new \Memcached();
$memcached->addServer(
$this->getParameter('app.memcached.host'),
$this->getParameter('app.memcached.port')
);
$memory = [
'app.add.post.remote.ip.delay' => md5(
sprintf(
'kevachat.app.add.post.remote.ip.delay:%s.%s',
$this->getParameter('app.name'),
$request->getClientIp(),
),
),
];
// Connect kevacoin
$client = new \Kevachat\Kevacoin\Client(
$this->getParameter('app.kevacoin.protocol'),
@ -188,13 +207,27 @@ class RoomController extends AbstractController @@ -188,13 +207,27 @@ class RoomController extends AbstractController
// Check namespace exist for this wallet
if (!in_array($request->get('namespace'), $namespaces))
{
exit('Namespace not related with this node!');
return $this->redirectToRoute(
'room_namespace',
[
'namespace' => $request->get('namespace'),
'message' => $request->get('message'),
'error' => $translator->trans('Namespace not related with this node!')
]
);
}
// Check namespace writable
if (!in_array($request->get('namespace'), (array) explode('|', $this->getParameter('app.kevacoin.room.namespaces'))))
{
exit('Namespace not listed in settings!');
return $this->redirectToRoute(
'room_namespace',
[
'namespace' => $request->get('namespace'),
'message' => $request->get('message'),
'error' => $translator->trans('Namespace not listed in settings!')
]
);
}
// Validate access to the room namespace
@ -202,6 +235,7 @@ class RoomController extends AbstractController @@ -202,6 +235,7 @@ class RoomController extends AbstractController
(
// Ignore this rule for is moderators
!in_array(
$request->getClientIp(),
(array) explode('|', $this->getParameter('app.add.post.remote.ip.moderators'))
) &&
@ -212,22 +246,107 @@ class RoomController extends AbstractController @@ -212,22 +246,107 @@ class RoomController extends AbstractController
)
)
{
exit('Namespace for read only!');
return $this->redirectToRoute(
'room_namespace',
[
'namespace' => $request->get('namespace'),
'message' => $request->get('message'),
'error' => $translator->trans('Namespace for read only!')
]
);
}
// Deny requests from banned remote hosts
if (in_array($request->getClientIp(), (array) explode('|', $this->getParameter('app.add.post.remote.ip.denied'))))
{
return $this->redirectToRoute(
'room_namespace',
[
'namespace' => $request->get('namespace'),
'message' => $request->get('message'),
'error' => $translator->trans('Access denied for this IP!')
]
);
}
// Validate remote IP regex
if (!preg_match($this->getParameter('app.add.post.remote.ip.regex'), $request->getClientIp()))
{
return $this->redirectToRoute(
'room_namespace',
[
'namespace' => $request->get('namespace'),
'message' => $request->get('message'),
'error' => $translator->trans('Access not allowed for this IP!')
]
);
}
// Validate remote IP limits
// Validate message regex
if (!preg_match($this->getParameter('app.add.post.value.regex'), $request->get('message')))
{
return $this->redirectToRoute(
'room_namespace',
[
'namespace' => $request->get('namespace'),
'message' => $request->get('message'),
'error' => sprintf(
$translator->trans('Message does not match node requirements: %s'),
$this->getParameter('app.add.post.value.regex')
)
]
);
}
// Validate funds
/// Validate remote IP limits
if ($delay = (int) $memcached->get($memory['app.add.post.remote.ip.delay']))
{
// Error
return $this->redirectToRoute(
'room_namespace',
[
'namespace' => $request->get('namespace'),
'message' => $request->get('message'),
'error' => sprintf(
$translator->trans('Please wait for %s seconds before post new message!'),
(int) $this->getParameter('app.add.post.remote.ip.delay') - (time() - $delay)
)
]
);
}
/// Validate funds available yet
if (1 > $client->getBalance())
{
return $this->redirectToRoute(
'room_namespace',
[
'namespace' => $request->get('namespace'),
'message' => $request->get('message'),
'error' => sprintf(
$translator->trans('Insufficient funds, wallet: %s'),
$this->getParameter('app.kevacoin.mine.address')
)
]
);
}
// @TODO Send message to DHT
// Register event time
$memcached->set(
$memory['app.add.post.remote.ip.delay'],
time(),
(int) $this->getParameter('app.add.post.remote.ip.delay')
);
// Redirect back to room
return $this->redirectToRoute(
'room_namespace',
[
'namespace' => $request->get('namespace')
'namespace' => $request->get('namespace'),
'error' => null,
'message' => null
]
);
}

5
templates/default/module/post.html.twig

@ -1,6 +1,9 @@ @@ -1,6 +1,9 @@
{% if enabled %}
<form name="post" action="{{ path('room_post', { namespace : namespace }) }}" method="post">
<textarea name="message" placeholder="{{ 'enter your message...' | trans }}">{{ message }}</textarea>
{% if error %}
<output name="error" for="form-post-message">{{ error }}</output>
{% endif %}
<textarea name="message" id="form-post-message" placeholder="{{ 'enter your message...' | trans }}">{{ message }}</textarea>
{% if user == 'anonymous' or user != 'ip' %}
<input type="radio" name="user" value="anonymous" id="form-post-user-anonymous" checked="checked" />
{% else %}

2
templates/default/room/index.html.twig

@ -24,7 +24,7 @@ @@ -24,7 +24,7 @@
</strong>
{% endif %}
&bull;
<a href="#{{ post.txid }}" title="{{ 'time:' | trans }} {{ post.transaction.time }} / {{ 'confirmations:' | trans }} {{ post.transaction.confirmations }}">{{ post.transaction.timestamp | format_ago }}</a>
<a href="{{ path('room_namespace', { namespace : request.get('namespace') }) }}#{{ post.txid }}" title="{{ 'time:' | trans }} {{ post.transaction.time }} / {{ 'confirmations:' | trans }} {{ post.transaction.confirmations }}">{{ post.transaction.timestamp | format_ago }}</a>
&bull;
<a href="{{ path('room_namespace', { namespace : request.get('namespace'), txid : post.txid }) }}#{{ post.txid }}">{{ 'quote' | trans }}</a>
<p>

Loading…
Cancel
Save