Browse Source

implement new room submit feature

main
ghost 12 months ago
parent
commit
7c51f3d57a
  1. 21
      .env
  2. 12
      composer.lock
  3. 5
      config/services.yaml
  4. 1
      public/css/default.css
  5. 38
      src/Controller/ModuleController.php
  6. 205
      src/Controller/RoomController.php
  7. 7
      templates/default/module/room.html.twig
  8. 2
      templates/default/module/rooms.html.twig
  9. 12
      templates/default/room/list.html.twig

21
.env

@ -19,7 +19,7 @@ APP_ENV=dev @@ -19,7 +19,7 @@ APP_ENV=dev
APP_SECRET=EDIT_ME
###< symfony/framework-bundle ###
APP_VERSION=1.3.1
APP_VERSION=1.4.0
APP_NAME=KevaChat
@ -61,23 +61,32 @@ APP_KEVACOIN_ROOM_NAMESPACE_DEFAULT=EDIT_ME @@ -61,23 +61,32 @@ APP_KEVACOIN_ROOM_NAMESPACE_DEFAULT=EDIT_ME
# Online session expiration timeout
APP_SESSION_ONLINE_TIMEOUT=900
# Moderators IP with extra permissions, separated with |
APP_MODERATOR_REMOTE_IP=
# Allow remotes to create new rooms (namespaces)
APP_ADD_ROOM_REMOTE_IP_REGEX=/.*/
# Time quota delay for new room submit ability per IP (seconds)
APP_ADD_ROOM_REMOTE_IP_DELAY=86400
# Skip access limits for banned IPs separated by |
APP_ADD_ROOM_REMOTE_IP_DENIED=
# Room name rules (for kevacoin _KEVA_NS_, max length 520)
APP_ADD_ROOM_KEVA_NS_VALUE_REGEX=/^[\w\s_-]{2,140}$/ui
# Allow remotes to create new posts (submit key/values)
APP_ADD_POST_REMOTE_IP_REGEX=/.*/
# Time quota for remote publications by IP (seconds)
# Time quota delay for post publications per IP (seconds)
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 ID rules (for kevacoin key) do not change to keep external KevaChat nodes compatibility
APP_ADD_POST_KEY_REGEX=/^([\d]+)@([A-z0-9\.\:\[\]]+)$/
# Post content rules (for kevacoin value)
# Post content rules (for kevacoin value, max length 3072)
APP_ADD_POST_VALUE_REGEX=/^[\w\s\:\.\,\'\"\/\!\?\@\#\%\(\)\[\]\+\-\*\$\%]{2,3072}$/ui

12
composer.lock generated

@ -132,16 +132,16 @@ @@ -132,16 +132,16 @@
},
{
"name": "kevachat/kevacoin",
"version": "1.4.2",
"version": "1.5.0",
"source": {
"type": "git",
"url": "https://github.com/kevachat/kevacoin-php.git",
"reference": "b6e5416c58d379fd197bbd6d1039a30042ea0481"
"reference": "44608e688f69ff1545f2a3103c4504bfb3294831"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/kevachat/kevacoin-php/zipball/b6e5416c58d379fd197bbd6d1039a30042ea0481",
"reference": "b6e5416c58d379fd197bbd6d1039a30042ea0481",
"url": "https://api.github.com/repos/kevachat/kevacoin-php/zipball/44608e688f69ff1545f2a3103c4504bfb3294831",
"reference": "44608e688f69ff1545f2a3103c4504bfb3294831",
"shasum": ""
},
"type": "library",
@ -156,9 +156,9 @@ @@ -156,9 +156,9 @@
],
"support": {
"issues": "https://github.com/kevachat/kevacoin-php/issues",
"source": "https://github.com/kevachat/kevacoin-php/tree/1.4.2"
"source": "https://github.com/kevachat/kevacoin-php/tree/1.5.0"
},
"time": "2023-12-06T09:20:08+00:00"
"time": "2023-12-09T18:55:04+00:00"
},
{
"name": "league/commonmark",

5
config/services.yaml

@ -24,12 +24,15 @@ parameters: @@ -24,12 +24,15 @@ parameters:
app.kevacoin.mine.solo.url: '%env(APP_KEVACOIN_MINE_SOLO_URL)%'
app.session.online.timeout: '%env(APP_SESSION_ONLINE_TIMEOUT)%'
app.add.room.remote.ip.regex: '%env(APP_ADD_ROOM_REMOTE_IP_REGEX)%'
app.add.room.remote.ip.delay: '%env(APP_ADD_ROOM_REMOTE_IP_DELAY)%'
app.add.room.remote.ip.denied: '%env(APP_ADD_ROOM_REMOTE_IP_DENIED)%'
app.add.room.keva.ns.value.regex: '%env(APP_ADD_ROOM_KEVA_NS_VALUE_REGEX)%'
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.key.regex: '%env(APP_ADD_POST_KEY_REGEX)%'
app.add.post.value.regex: '%env(APP_ADD_POST_VALUE_REGEX)%'
app.moderator.remote.ip: '%env(APP_MODERATOR_REMOTE_IP)%'
services:
# default configuration for services in *this* file

1
public/css/default.css

@ -155,6 +155,7 @@ footer > form @@ -155,6 +155,7 @@ footer > form
width: 100%;
}
footer > form > input[type="text"],
footer > form > textarea
{
box-sizing: border-box;

38
src/Controller/ModuleController.php

@ -99,18 +99,27 @@ class ModuleController extends AbstractController @@ -99,18 +99,27 @@ class ModuleController extends AbstractController
Request $request
): Response
{
$client = new \Kevachat\Kevacoin\Client(
$this->getParameter('app.kevacoin.protocol'),
$this->getParameter('app.kevacoin.host'),
$this->getParameter('app.kevacoin.port'),
$this->getParameter('app.kevacoin.username'),
$this->getParameter('app.kevacoin.password')
);
// Create rooms list
$list = [];
foreach ((array) explode('|', $this->getParameter('app.kevacoin.room.namespaces.pinned')) as $room)
{
$list[] = $room;
}
// Append custom valid namespace to the rooms list menu
if (!in_array($request->get('namespace'), $list) && preg_match('/^[A-z0-9]{34}$/', $request->get('namespace')))
{
$list[] = $request->get('namespace');
}
// Render the template
return $this->render(
'default/module/rooms.html.twig',
[
'list' => (array) explode('|', $this->getParameter('app.kevacoin.room.namespaces.pinned')),
'list' => array_unique(
$list
),
'form' =>
[
'namespace' =>
@ -178,4 +187,17 @@ class ModuleController extends AbstractController @@ -178,4 +187,17 @@ class ModuleController extends AbstractController
]
);
}
public function room(
Request $request
): Response
{
return $this->render(
'default/module/room.html.twig',
[
'name' => $request->get('name'),
'error' => $request->get('error')
]
);
}
}

205
src/Controller/RoomController.php

@ -95,9 +95,9 @@ class RoomController extends AbstractController @@ -95,9 +95,9 @@ class RoomController extends AbstractController
array_multisort(
array_column(
$list,
'name'
'total'
),
SORT_ASC,
SORT_DESC,
$list
);
@ -165,7 +165,7 @@ class RoomController extends AbstractController @@ -165,7 +165,7 @@ class RoomController extends AbstractController
$feed = [];
// Get pending paradise
foreach ((array) $client->kevaPending() as $pending)
foreach ((array) $client->kevaPending() as $pending) // @TODO relate to this room
{
// Ignore pending posts from other rooms
if ($pending['namespace'] !== $request->get('namespace'))
@ -347,7 +347,7 @@ class RoomController extends AbstractController @@ -347,7 +347,7 @@ class RoomController extends AbstractController
$this->getParameter('app.kevacoin.password')
);
// Check namespace defined in config
// Check namespace available on this wallet
$rooms = [];
foreach ((array) $client->kevaListNamespaces() as $value)
@ -373,7 +373,7 @@ class RoomController extends AbstractController @@ -373,7 +373,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'))
(array) explode('|', $this->getParameter('app.moderator.remote.ip'))
) &&
// Check namespace writable or user is moderator
@ -401,7 +401,10 @@ class RoomController extends AbstractController @@ -401,7 +401,10 @@ class RoomController extends AbstractController
[
'namespace' => $request->get('namespace'),
'message' => $request->get('message'),
'error' => $translator->trans('Access denied for this IP!')
'error' => sprintf(
$translator->trans('Access denied for host %s!'),
$request->getClientIp()
)
]
);
}
@ -414,7 +417,10 @@ class RoomController extends AbstractController @@ -414,7 +417,10 @@ class RoomController extends AbstractController
[
'namespace' => $request->get('namespace'),
'message' => $request->get('message'),
'error' => $translator->trans('Access not allowed for this IP!')
'error' => sprintf(
$translator->trans('Access restricted for host %s!'),
$request->getClientIp()
)
]
);
}
@ -445,7 +451,7 @@ class RoomController extends AbstractController @@ -445,7 +451,7 @@ class RoomController extends AbstractController
'namespace' => $request->get('namespace'),
'message' => $request->get('message'),
'error' => sprintf(
$translator->trans('Please wait for %s seconds before post new message!'),
$translator->trans('Please wait %s seconds before post new message!'),
(int) $this->getParameter('app.add.post.remote.ip.delay') - (time() - $delay)
)
]
@ -462,7 +468,7 @@ class RoomController extends AbstractController @@ -462,7 +468,7 @@ class RoomController extends AbstractController
'message' => $request->get('message'),
'error' => sprintf(
$translator->trans('Insufficient funds, wallet: %s'),
$this->getParameter('app.kevacoin.mine.address')
$this->getParameter('app.kevacoin.boost.address')
)
]
);
@ -510,6 +516,187 @@ class RoomController extends AbstractController @@ -510,6 +516,187 @@ class RoomController extends AbstractController
);
}
#[Route(
'/room/add',
name: 'room_add',
methods:
[
'POST'
]
)]
public function add(
Request $request,
TranslatorInterface $translator
): Response
{
// Check maintenance mode disabled
if ($this->getParameter('app.maintenance'))
{
return $this->redirectToRoute(
'room_namespace',
[
'namespace' => $request->get('namespace'),
'message' => $request->get('message'),
'error' => $this->getParameter('app.maintenance')
]
);
}
// Connect memcached
$memcached = new \Memcached();
$memcached->addServer(
$this->getParameter('app.memcached.host'),
$this->getParameter('app.memcached.port')
);
$memory = md5(
sprintf(
'%s.RoomController::add:add.room.remote.ip.delay:%s',
__DIR__,
$request->getClientIp(),
),
);
// Connect kevacoin
$client = new \Kevachat\Kevacoin\Client(
$this->getParameter('app.kevacoin.protocol'),
$this->getParameter('app.kevacoin.host'),
$this->getParameter('app.kevacoin.port'),
$this->getParameter('app.kevacoin.username'),
$this->getParameter('app.kevacoin.password')
);
// Trim extra spaces from room name
$name = trim(
$request->get('name')
);
// Validate room name regex
if (!preg_match($this->getParameter('app.add.room.keva.ns.value.regex'), $name))
{
return $this->redirectToRoute(
'room_list',
[
'name' => $name,
'error' => sprintf(
$translator->trans('Room name does not match node requirements: %s'),
$this->getParameter('app.add.room.keva.ns.value.regex')
)
]
);
}
// Check room name not added before
$rooms = [];
foreach ((array) $client->kevaListNamespaces() as $value)
{
$rooms[$value['namespaceId']] = $value['displayName'];
}
if (in_array($name, $rooms))
{
return $this->redirectToRoute(
'room_list',
[
'name' => $name,
'error' => $translator->trans('Room with same name already exists on this node!')
]
);
}
// Deny requests from banned remote hosts
if (in_array($request->getClientIp(), (array) explode('|', $this->getParameter('app.add.room.remote.ip.denied'))))
{
return $this->redirectToRoute(
'room_list',
[
'name' => $name,
'error' => sprintf(
$translator->trans('Access denied for host %s!'),
$request->getClientIp()
)
]
);
}
// Validate remote IP regex
if (!preg_match($this->getParameter('app.add.room.remote.ip.regex'), $request->getClientIp()))
{
return $this->redirectToRoute(
'room_list',
[
'name' => $name,
'error' => sprintf(
$translator->trans('Access restricted for host %s!'),
$request->getClientIp()
)
]
);
}
// Validate remote IP limits
if ($delay = (int) $memcached->get($memory))
{
// Error
return $this->redirectToRoute(
'room_list',
[
'name' => $name,
'error' => sprintf(
$translator->trans('Please wait for %s seconds before add new room!'),
(int) $this->getParameter('app.add.room.remote.ip.delay') - (time() - $delay)
)
]
);
}
// Validate funds available yet
if (1 > $client->getBalance())
{
return $this->redirectToRoute(
'room_list',
[
'name' => $name,
'error' => sprintf(
$translator->trans('Insufficient funds, wallet: %s'),
$this->getParameter('app.kevacoin.boost.address')
)
]
);
}
// Send message to DHT
if ($namespace = $client->kevaNamespace($name))
{
// Register event time
$memcached->set(
$memory,
time(),
(int) $this->getParameter('app.add.room.remote.ip.delay') // auto remove on cache expire
);
// Redirect to new room
return $this->redirectToRoute(
'room_namespace',
[
'namespace' => $namespace['namespaceId'],
'error' => null,
'message' => null
]
);
}
// Something went wrong, return error message
return $this->redirectToRoute(
'room_list',
[
'name' => $name,
'error' => $translator->trans('Internal error! Please feedback')
]
);
}
private function _post(array $data): ?object
{
// Validate key format allowed in settings

7
templates/default/module/room.html.twig

@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
<form name="room" action="{{ path('room_add') }}" method="post">
{% if error %}
<output name="error" for="form-room-name">{{ error }}</output>
{% endif %}
<input type="text" name="name" id="form-room-name" value="{{ name }}" placeholder="{{ 'enter new room name...' | trans }}" />
<button type="submit">{{ 'add' | trans }}</button>
</form>

2
templates/default/module/rooms.html.twig

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
<form name="room" action="{{ path('room_index') }}" method="get">
<form name="rooms" action="{{ path('room_index') }}" method="get">
<input type="text" name="namespace" value="{{ form.namespace.value }}" placeholder="{{ 'join room by kevacoin namespace...' | trans }}" />
</form>
{% if list %}

12
templates/default/room/list.html.twig

@ -43,4 +43,16 @@ @@ -43,4 +43,16 @@
</li>
</ul>
{% endif %}
{% endblock %}
{% block footer_content %}
{{
render(
controller(
'App\\Controller\\ModuleController::room',
{
request: request
}
)
)
}}
{% endblock %}
Loading…
Cancel
Save