From d4e450b6af2824daf0159b5f3668603fd2c7b8f6 Mon Sep 17 00:00:00 2001 From: ghost Date: Wed, 6 Dec 2023 00:44:38 +0200 Subject: [PATCH] implement post validation --- .env | 9 +- config/services.yaml | 4 +- public/css/default.css | 8 ++ src/Controller/ModuleController.php | 3 +- src/Controller/RoomController.php | 133 ++++++++++++++++++++++-- templates/default/module/post.html.twig | 5 +- templates/default/room/index.html.twig | 2 +- 7 files changed, 152 insertions(+), 12 deletions(-) diff --git a/.env b/.env index 532e120..e565af1 100644 --- a/.env +++ b/.env @@ -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 # 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}/ \ No newline at end of file +APP_ADD_POST_VALUE_REGEX=/^[\w\s]{2,3072}$/ui \ No newline at end of file diff --git a/config/services.yaml b/config/services.yaml index 253487f..c43c3ae 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -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: 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: diff --git a/public/css/default.css b/public/css/default.css index 6315655..0cb985a 100644 --- a/public/css/default.css +++ b/public/css/default.css @@ -146,4 +146,12 @@ footer > form > button cursor: pointer; float: right; padding: 2px 8px; +} + +footer > form > output +{ + color: #ff6363; + display: block; + font-weight: bolder; + margin-bottom: 16px; } \ No newline at end of file diff --git a/src/Controller/ModuleController.php b/src/Controller/ModuleController.php index 992d52e..ca519a7 100644 --- a/src/Controller/ModuleController.php +++ b/src/Controller/ModuleController.php @@ -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() ] ); diff --git a/src/Controller/RoomController.php b/src/Controller/RoomController.php index 5ddb020..cb118a9 100644 --- a/src/Controller/RoomController.php +++ b/src/Controller/RoomController.php @@ -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 ] )] 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 // 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 ( // 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 ) ) { - 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 ] ); } diff --git a/templates/default/module/post.html.twig b/templates/default/module/post.html.twig index 63fe791..75c2c77 100644 --- a/templates/default/module/post.html.twig +++ b/templates/default/module/post.html.twig @@ -1,6 +1,9 @@ {% if enabled %}
- + {% if error %} + {{ error }} + {% endif %} + {% if user == 'anonymous' or user != 'ip' %} {% else %} diff --git a/templates/default/room/index.html.twig b/templates/default/room/index.html.twig index dc46468..acf860c 100644 --- a/templates/default/room/index.html.twig +++ b/templates/default/room/index.html.twig @@ -24,7 +24,7 @@ {% endif %} • - {{ post.transaction.timestamp | format_ago }} + {{ post.transaction.timestamp | format_ago }}{{ 'quote' | trans }}