mirror of
https://github.com/bitinflow/expose.git
synced 2026-03-13 13:35:54 +00:00
Allow specifying maximum connection counts per user
This commit is contained in:
@@ -6,6 +6,7 @@ use App\Contracts\ConnectionManager as ConnectionManagerContract;
|
||||
use App\Contracts\SubdomainGenerator;
|
||||
use App\Http\QueryParameters;
|
||||
use App\Server\Exceptions\NoFreePortAvailable;
|
||||
use Illuminate\Support\Collection;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use React\EventLoop\LoopInterface;
|
||||
use React\Socket\Server;
|
||||
@@ -157,6 +158,20 @@ class ConnectionManager implements ConnectionManagerContract
|
||||
});
|
||||
}
|
||||
|
||||
public function findControlConnectionsForIp(string $ip): array
|
||||
{
|
||||
return collect($this->connections)->filter(function (ControlConnection $connection) use ($ip) {
|
||||
return $connection->socket->remoteAddress == $ip;
|
||||
})->toArray();
|
||||
}
|
||||
|
||||
public function findControlConnectionsForAuthToken(string $token): array
|
||||
{
|
||||
return collect($this->connections)->filter(function (ControlConnection $connection) use ($token) {
|
||||
return $connection->authToken === $token;
|
||||
})->toArray();
|
||||
}
|
||||
|
||||
public function getConnections(): array
|
||||
{
|
||||
return $this->connections;
|
||||
|
||||
@@ -41,6 +41,7 @@ class StoreUsersController extends AdminController
|
||||
'auth_token' => (string) Str::uuid(),
|
||||
'can_specify_subdomains' => (int) $request->get('can_specify_subdomains'),
|
||||
'can_share_tcp_ports' => (int) $request->get('can_share_tcp_ports'),
|
||||
'max_connections' => (int) $request->get('max_connections'),
|
||||
];
|
||||
|
||||
$this->userRepository
|
||||
|
||||
@@ -7,11 +7,13 @@ use App\Contracts\SubdomainRepository;
|
||||
use App\Contracts\UserRepository;
|
||||
use App\Http\QueryParameters;
|
||||
use App\Server\Exceptions\NoFreePortAvailable;
|
||||
use Illuminate\Support\Arr;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use Ratchet\WebSocket\MessageComponentInterface;
|
||||
use React\Promise\Deferred;
|
||||
use React\Promise\PromiseInterface;
|
||||
use stdClass;
|
||||
use function React\Promise\reject;
|
||||
|
||||
class ControlMessageController implements MessageComponentInterface
|
||||
{
|
||||
@@ -85,7 +87,35 @@ class ControlMessageController implements MessageComponentInterface
|
||||
|
||||
protected function authenticate(ConnectionInterface $connection, $data)
|
||||
{
|
||||
if (! isset($data->subdomain)) {
|
||||
$data->subdomain = null;
|
||||
}
|
||||
|
||||
$this->verifyAuthToken($connection)
|
||||
->then(function ($user) use ($connection) {
|
||||
$maximumConnectionCount = config('expose.admin.maximum_open_connections_per_user', 0);
|
||||
|
||||
if (is_null($user)) {
|
||||
$connectionCount = count($this->connectionManager->findControlConnectionsForIp($connection->remoteAddress));
|
||||
} else {
|
||||
$maximumConnectionCount = Arr::get($user, 'max_connections', $maximumConnectionCount);
|
||||
|
||||
$connectionCount = count($this->connectionManager->findControlConnectionsForAuthToken($user['auth_token']));
|
||||
}
|
||||
|
||||
if ($maximumConnectionCount > 0 && $connectionCount + 1 > $maximumConnectionCount) {
|
||||
$connection->send(json_encode([
|
||||
'event' => 'authenticationFailed',
|
||||
'data' => [
|
||||
'message' => config('expose.admin.messages.maximum_connection_count'),
|
||||
],
|
||||
]));
|
||||
$connection->close();
|
||||
|
||||
reject(null);
|
||||
}
|
||||
return $user;
|
||||
})
|
||||
->then(function ($user) use ($connection, $data) {
|
||||
if ($data->type === 'http') {
|
||||
$this->handleHttpConnection($connection, $data, $user);
|
||||
|
||||
@@ -132,8 +132,8 @@ class DatabaseUserRepository implements UserRepository
|
||||
$deferred = new Deferred();
|
||||
|
||||
$this->database->query("
|
||||
INSERT INTO users (name, auth_token, can_specify_subdomains, can_share_tcp_ports, created_at)
|
||||
VALUES (:name, :auth_token, :can_specify_subdomains, :can_share_tcp_ports, DATETIME('now'))
|
||||
INSERT INTO users (name, auth_token, can_specify_subdomains, can_share_tcp_ports, max_connections, created_at)
|
||||
VALUES (:name, :auth_token, :can_specify_subdomains, :can_share_tcp_ports, :max_connections, DATETIME('now'))
|
||||
", $data)
|
||||
->then(function (Result $result) use ($deferred) {
|
||||
$this->database->query('SELECT * FROM users WHERE id = :id', ['id' => $result->insertId])
|
||||
|
||||
Reference in New Issue
Block a user