From b515a55325aca70db47e76f980160a519b805c01 Mon Sep 17 00:00:00 2001 From: Marcel Pociot Date: Wed, 29 Apr 2020 22:05:03 +0200 Subject: [PATCH] wip --- app/Client/Factory.php | 2 +- .../Controllers/AttachDataToLogController.php | 4 +- .../Http/Controllers/ClearLogsController.php | 18 ++----- .../Http/Controllers/DashboardController.php | 18 +++---- app/Client/Http/Controllers/LogController.php | 13 ++--- .../PushLogsToDashboardController.php | 53 +++++-------------- .../Http/Controllers/ReplayLogController.php | 29 +++------- .../Modifiers/CheckBasicAuthentication.php | 3 +- app/Http/Controllers/Concerns/LoadsViews.php | 24 +++++++++ .../ParsesIncomingRequest.php} | 46 ++++------------ app/Http/Controllers/Controller.php | 52 +++++++++++------- app/Server/Factory.php | 6 +-- .../Controllers/Admin/AdminController.php | 37 +++++++++++++ .../Admin/DeleteUsersController.php | 4 +- .../Controllers/Admin/ListSitesController.php | 4 +- .../Controllers/Admin/ListUsersController.php | 4 +- .../Controllers/Admin/LoginController.php | 25 --------- .../Admin/RedirectToUsersController.php | 20 +++++++ .../Admin/StoreUsersController.php | 4 +- .../Admin/VerifyLoginController.php | 51 ------------------ .../Controllers/ControlMessageController.php | 2 +- .../Controllers/TunnelMessageController.php | 4 +- app/helpers.php | 2 +- config/expose.php | 30 ++++++++++- tests/Feature/Client/DashboardTest.php | 1 + tests/Feature/Server/AdminTest.php | 8 +++ tests/Feature/{Client => }/TestCase.php | 4 +- 27 files changed, 215 insertions(+), 253 deletions(-) create mode 100644 app/Http/Controllers/Concerns/LoadsViews.php rename app/Http/Controllers/{PostController.php => Concerns/ParsesIncomingRequest.php} (59%) create mode 100644 app/Server/Http/Controllers/Admin/AdminController.php delete mode 100644 app/Server/Http/Controllers/Admin/LoginController.php create mode 100644 app/Server/Http/Controllers/Admin/RedirectToUsersController.php delete mode 100644 app/Server/Http/Controllers/Admin/VerifyLoginController.php create mode 100644 tests/Feature/Server/AdminTest.php rename tests/Feature/{Client => }/TestCase.php (93%) diff --git a/app/Client/Factory.php b/app/Client/Factory.php index 46f18cb..f2f411c 100644 --- a/app/Client/Factory.php +++ b/app/Client/Factory.php @@ -104,7 +104,7 @@ class Factory $this->router->post('/logs', PushLogsToDashboardController::class); $this->router->get('/replay/{log}', ReplayLogController::class); $this->router->post('/logs/{request_id}/data', AttachDataToLogController::class); - $this->router->post('/logs/clear', ClearLogsController::class); + $this->router->get('/logs/clear', ClearLogsController::class); $this->app->route('/socket', new WsServer(new Socket()), ['*']); diff --git a/app/Client/Http/Controllers/AttachDataToLogController.php b/app/Client/Http/Controllers/AttachDataToLogController.php index 6e1ae0d..f9096fd 100644 --- a/app/Client/Http/Controllers/AttachDataToLogController.php +++ b/app/Client/Http/Controllers/AttachDataToLogController.php @@ -2,14 +2,14 @@ namespace App\Client\Http\Controllers; -use App\Http\Controllers\PostController; +use App\Http\Controllers\Controller; use GuzzleHttp\Psr7\Response; use Illuminate\Http\Request; use App\Logger\RequestLogger; use Ratchet\ConnectionInterface; use function GuzzleHttp\Psr7\str; -class AttachDataToLogController extends PostController +class AttachDataToLogController extends Controller { /** @var RequestLogger */ protected $requestLogger; diff --git a/app/Client/Http/Controllers/ClearLogsController.php b/app/Client/Http/Controllers/ClearLogsController.php index cd06a7f..641dc0e 100644 --- a/app/Client/Http/Controllers/ClearLogsController.php +++ b/app/Client/Http/Controllers/ClearLogsController.php @@ -2,14 +2,10 @@ namespace App\Client\Http\Controllers; -use App\Client\Http\HttpClient; use App\Http\Controllers\Controller; -use App\Http\QueryParameters; use App\Logger\RequestLogger; -use GuzzleHttp\Psr7\Response; +use Illuminate\Http\Request; use Ratchet\ConnectionInterface; -use function GuzzleHttp\Psr7\str; -use Psr\Http\Message\RequestInterface; class ClearLogsController extends Controller { @@ -21,18 +17,10 @@ class ClearLogsController extends Controller $this->requestLogger = $requestLogger; } - public function onOpen(ConnectionInterface $connection, RequestInterface $request = null) + public function handle(Request $request, ConnectionInterface $httpConnection) { $this->requestLogger->clear(); - $connection->send( - str(new Response( - 200, - ['Content-Type' => 'application/json'], - '' - )) - ); - - $connection->close(); + $httpConnection->send(respond_json([], 200)); } } diff --git a/app/Client/Http/Controllers/DashboardController.php b/app/Client/Http/Controllers/DashboardController.php index 3d2736a..da2064e 100644 --- a/app/Client/Http/Controllers/DashboardController.php +++ b/app/Client/Http/Controllers/DashboardController.php @@ -5,24 +5,18 @@ namespace App\Client\Http\Controllers; use App\Client\Client; use App\Http\Controllers\Controller; use GuzzleHttp\Psr7\Response; +use Illuminate\Http\Request; use function GuzzleHttp\Psr7\str; use Psr\Http\Message\RequestInterface; use Ratchet\ConnectionInterface; class DashboardController extends Controller { - public function onOpen(ConnectionInterface $connection, RequestInterface $request = null) - { - $connection->send( - str(new Response( - 200, - ['Content-Type' => 'text/html'], - $this->getView('client.dashboard', [ - 'subdomains' => Client::$subdomains, - ]) - )) - ); - $connection->close(); + public function handle(Request $request, ConnectionInterface $httpConnection) + { + $httpConnection->send(respond_html($this->getView('client.dashboard', [ + 'subdomains' => Client::$subdomains, + ]))); } } diff --git a/app/Client/Http/Controllers/LogController.php b/app/Client/Http/Controllers/LogController.php index af6166c..32675ae 100644 --- a/app/Client/Http/Controllers/LogController.php +++ b/app/Client/Http/Controllers/LogController.php @@ -5,6 +5,7 @@ namespace App\Client\Http\Controllers; use App\Http\Controllers\Controller; use App\Logger\RequestLogger; use GuzzleHttp\Psr7\Response; +use Illuminate\Http\Request; use Ratchet\ConnectionInterface; use function GuzzleHttp\Psr7\str; use Psr\Http\Message\RequestInterface; @@ -19,16 +20,8 @@ class LogController extends Controller $this->requestLogger = $requestLogger; } - public function onOpen(ConnectionInterface $connection, RequestInterface $request = null) + public function handle(Request $request, ConnectionInterface $httpConnection) { - $connection->send( - str(new Response( - 200, - ['Content-Type' => 'application/json'], - json_encode($this->requestLogger->getData(), JSON_INVALID_UTF8_IGNORE) - )) - ); - - $connection->close(); + $httpConnection->send(respond_json($this->requestLogger->getData())); } } diff --git a/app/Client/Http/Controllers/PushLogsToDashboardController.php b/app/Client/Http/Controllers/PushLogsToDashboardController.php index 064aea5..6df7ce9 100644 --- a/app/Client/Http/Controllers/PushLogsToDashboardController.php +++ b/app/Client/Http/Controllers/PushLogsToDashboardController.php @@ -6,6 +6,7 @@ use App\Http\Controllers\Controller; use Exception; use App\WebSockets\Socket; use GuzzleHttp\Psr7\Response; +use Illuminate\Http\Request; use Illuminate\Support\Collection; use Ratchet\ConnectionInterface; use function GuzzleHttp\Psr7\str; @@ -14,50 +15,20 @@ use Psr\Http\Message\RequestInterface; class PushLogsToDashboardController extends Controller { - public function onOpen(ConnectionInterface $connection, RequestInterface $request = null) + public function handle(Request $request, ConnectionInterface $httpConnection) { - $connection->contentLength = $this->findContentLength($request->getHeaders()); - - $connection->requestBuffer = (string) $request->getBody(); - - $this->checkContentLength($connection); - } - - public function onMessage(ConnectionInterface $from, $msg) - { - $from->requestBuffer .= $msg; - - $this->checkContentLength($from); - } - - protected function findContentLength(array $headers): int - { - return Collection::make($headers)->first(function ($values, $header) { - return strtolower($header) === 'content-length'; - })[0] ?? 0; - } - - protected function checkContentLength(ConnectionInterface $connection) - { - if (strlen($connection->requestBuffer) === $connection->contentLength) { - try { - /* - * This is the post payload from our PHPUnit tests. - * Send it to the connected connections. - */ - foreach (Socket::$connections as $webSocketConnection) { - $webSocketConnection->send($connection->requestBuffer); - } - - $connection->send(str(new Response(200))); - } catch (Exception $e) { - $connection->send(str(new Response(500, [], $e->getMessage()))); + try { + /* + * This is the post payload from our PHPUnit tests. + * Send it to the connected connections. + */ + foreach (Socket::$connections as $webSocketConnection) { + $webSocketConnection->send($request->getContent()); } - $connection->close(); - - unset($connection->requestBuffer); - unset($connection->contentLength); + $httpConnection->send(str(new Response(200))); + } catch (Exception $e) { + $httpConnection->send(str(new Response(500, [], $e->getMessage()))); } } } diff --git a/app/Client/Http/Controllers/ReplayLogController.php b/app/Client/Http/Controllers/ReplayLogController.php index 2da026c..9cc1a22 100644 --- a/app/Client/Http/Controllers/ReplayLogController.php +++ b/app/Client/Http/Controllers/ReplayLogController.php @@ -7,6 +7,7 @@ use App\Http\Controllers\Controller; use App\Http\QueryParameters; use App\Logger\RequestLogger; use GuzzleHttp\Psr7\Response; +use Illuminate\Http\Request; use Ratchet\ConnectionInterface; use function GuzzleHttp\Psr7\str; use Psr\Http\Message\RequestInterface; @@ -25,35 +26,17 @@ class ReplayLogController extends Controller $this->httpClient = $httpClient; } - public function onOpen(ConnectionInterface $connection, RequestInterface $request = null) + public function handle(Request $request, ConnectionInterface $httpConnection) { - $loggedRequest = $this->requestLogger->findLoggedRequest(QueryParameters::create($request)->get('log')); + $loggedRequest = $this->requestLogger->findLoggedRequest($request->get('log')); if (is_null($loggedRequest)) { - $connection->send( - str(new Response( - 404, - ['Content-Type' => 'application/json'], - )) - ); - - $connection->close(); + $httpConnection->send(str(new Response(404))); return; } - $requestData = $loggedRequest->getRequestData(); + $this->httpClient->performRequest($loggedRequest->getRequestData()); - /** @var HttpClient $tunnel */ - $this->httpClient->performRequest($requestData); - - $connection->send( - str(new Response( - 200, - ['Content-Type' => 'application/json'], - '' - )) - ); - - $connection->close(); + $httpConnection->send(str(new Response(200))); } } diff --git a/app/Client/Http/Modifiers/CheckBasicAuthentication.php b/app/Client/Http/Modifiers/CheckBasicAuthentication.php index 48ab8ff..ca68445 100644 --- a/app/Client/Http/Modifiers/CheckBasicAuthentication.php +++ b/app/Client/Http/Modifiers/CheckBasicAuthentication.php @@ -3,6 +3,7 @@ namespace App\Client\Http\Modifiers; use App\Client\Configuration; +use GuzzleHttp\Psr7\Response; use Illuminate\Support\Arr; use Psr\Http\Message\RequestInterface; use Ratchet\Client\WebSocket; @@ -28,7 +29,7 @@ class CheckBasicAuthentication if (is_null($username)) { $proxyConnection->send( - str(new \GuzzleHttp\Psr7\Response(401, [ + str(new Response(401, [ 'WWW-Authenticate' => 'Basic realm=Expose' ], 'Unauthorized')) ); diff --git a/app/Http/Controllers/Concerns/LoadsViews.php b/app/Http/Controllers/Concerns/LoadsViews.php new file mode 100644 index 0000000..5665708 --- /dev/null +++ b/app/Http/Controllers/Concerns/LoadsViews.php @@ -0,0 +1,24 @@ + file_get_contents(base_path('resources/views/server/layouts/app.twig')), + 'template' => file_get_contents(base_path('resources/views/'.$templatePath.'.twig')), + ]) + ); + + return stream_for($twig->render('template', $data)); + } +} diff --git a/app/Http/Controllers/PostController.php b/app/Http/Controllers/Concerns/ParsesIncomingRequest.php similarity index 59% rename from app/Http/Controllers/PostController.php rename to app/Http/Controllers/Concerns/ParsesIncomingRequest.php index e198112..5342806 100644 --- a/app/Http/Controllers/PostController.php +++ b/app/Http/Controllers/Concerns/ParsesIncomingRequest.php @@ -1,45 +1,16 @@ contentLength = $this->findContentLength($request->getHeaders()); - - $connection->requestBuffer = (string) $request->getBody(); - - $connection->request = $request; - - $this->checkContentLength($connection); - } - - public function onMessage(ConnectionInterface $from, $msg) - { - if (! isset($from->requestBuffer)) { - $request = parse_request($msg); - $from->contentLength = $this->findContentLength($request->getHeaders()); - $from->request = $request; - $from->requestBuffer = (string) $request->getBody(); - } else { - $from->requestBuffer .= $msg; - } - - $this->checkContentLength($from); - } - protected function findContentLength(array $headers): int { return Collection::make($headers)->first(function ($values, $header) { @@ -47,14 +18,21 @@ abstract class PostController extends Controller })[0] ?? 0; } + protected function shouldHandleRequest(Request $request, ConnectionInterface $httpConnection): bool + { + return true; + } + protected function checkContentLength(ConnectionInterface $connection) { if (strlen($connection->requestBuffer) === $connection->contentLength) { $laravelRequest = $this->createLaravelRequest($connection); - $this->handle($laravelRequest, $connection); + if ($this->shouldHandleRequest($laravelRequest, $connection)) { + $this->handle($laravelRequest, $connection); + } - if (! $this->keepConnectionOpen) { + if (!$this->keepConnectionOpen) { $connection->close(); } @@ -64,8 +42,6 @@ abstract class PostController extends Controller } } - abstract public function handle(Request $request, ConnectionInterface $httpConnection); - protected function createLaravelRequest(ConnectionInterface $connection): Request { try { diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index b106514..b871662 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -2,15 +2,30 @@ namespace App\Http\Controllers; -use Exception; +use App\Http\Controllers\Concerns\LoadsViews; +use App\Http\Controllers\Concerns\ParsesIncomingRequest; +use Illuminate\Http\Request; +use Psr\Http\Message\RequestInterface; use Ratchet\ConnectionInterface; use Ratchet\Http\HttpServerInterface; -use Twig\Environment; -use Twig\Loader\ArrayLoader; -use function GuzzleHttp\Psr7\stream_for; abstract class Controller implements HttpServerInterface { + use LoadsViews, ParsesIncomingRequest; + + protected $keepConnectionOpen = false; + + public function onOpen(ConnectionInterface $connection, RequestInterface $request = null) + { + $connection->contentLength = $this->findContentLength($request->getHeaders()); + + $connection->requestBuffer = (string) $request->getBody(); + + $connection->request = $request; + + $this->checkContentLength($connection); + } + public function onClose(ConnectionInterface $connection) { unset($connection->requestBuffer); @@ -18,25 +33,24 @@ abstract class Controller implements HttpServerInterface unset($connection->request); } - public function onError(ConnectionInterface $connection, Exception $e) - { - } - public function onMessage(ConnectionInterface $from, $msg) { + if (! isset($from->requestBuffer)) { + $request = parse_request($msg); + $from->contentLength = $this->findContentLength($request->getHeaders()); + $from->request = $request; + $from->requestBuffer = (string) $request->getBody(); + } else { + $from->requestBuffer .= $msg; + } + + $this->checkContentLength($from); } - protected function getView(string $view, array $data = []) + function onError(ConnectionInterface $conn, \Exception $e) { - $templatePath = implode(DIRECTORY_SEPARATOR, explode('.', $view)); - - $twig = new Environment( - new ArrayLoader([ - 'app' => file_get_contents(base_path('resources/views/server/layouts/app.twig')), - 'template' => file_get_contents(base_path('resources/views/'.$templatePath.'.twig')), - ]) - ); - - return stream_for($twig->render('template', $data)); + // } + + abstract public function handle(Request $request, ConnectionInterface $httpConnection); } diff --git a/app/Server/Factory.php b/app/Server/Factory.php index 14e130e..051ad03 100644 --- a/app/Server/Factory.php +++ b/app/Server/Factory.php @@ -10,6 +10,7 @@ use App\Server\Http\Controllers\Admin\DeleteUsersController; use App\Server\Http\Controllers\Admin\ListSitesController; use App\Server\Http\Controllers\Admin\ListUsersController; use App\Server\Http\Controllers\Admin\LoginController; +use App\Server\Http\Controllers\Admin\RedirectToUsersController; use App\Server\Http\Controllers\Admin\StoreUsersController; use App\Server\Http\Controllers\Admin\VerifyLoginController; use App\Server\Http\Controllers\ControlMessageController; @@ -106,10 +107,9 @@ class Factory protected function addAdminRoutes() { - $adminCondition = 'request.headers.get("Host") matches "/'.config('expose.dashboard_subdomain').'\./i"'; + $adminCondition = 'request.headers.get("Host") matches "/'.config('expose.admin.subdomain').'\./i"'; - $this->router->get('/', LoginController::class, $adminCondition); - $this->router->post('/', VerifyLoginController::class, $adminCondition); + $this->router->get('/', RedirectToUsersController::class, $adminCondition); $this->router->get('/users', ListUsersController::class, $adminCondition); $this->router->post('/users', StoreUsersController::class, $adminCondition); $this->router->delete('/users/delete/{id}', DeleteUsersController::class, $adminCondition); diff --git a/app/Server/Http/Controllers/Admin/AdminController.php b/app/Server/Http/Controllers/Admin/AdminController.php new file mode 100644 index 0000000..6172498 --- /dev/null +++ b/app/Server/Http/Controllers/Admin/AdminController.php @@ -0,0 +1,37 @@ +header('Authorization'), 'Basic '); + $authParts = explode(':', base64_decode($authorization), 2); + list($user, $password) = $authParts; + + if (! $this->credentialsAreAllowed($user, $password)) { + throw new \InvalidArgumentException('Invalid Login'); + } + return true; + } catch (\Throwable $e) { + $httpConnection->send(str(new Response(401, [ + 'WWW-Authenticate' => 'Basic realm="Expose"' + ], 'foo'))); + } + return false; + } + + protected function credentialsAreAllowed(string $user, string $password) + { + return config('expose.admin.users.'.$user) === $password; + } +} diff --git a/app/Server/Http/Controllers/Admin/DeleteUsersController.php b/app/Server/Http/Controllers/Admin/DeleteUsersController.php index 5b0c72c..b90934a 100644 --- a/app/Server/Http/Controllers/Admin/DeleteUsersController.php +++ b/app/Server/Http/Controllers/Admin/DeleteUsersController.php @@ -2,7 +2,7 @@ namespace App\Server\Http\Controllers\Admin; -use App\Http\Controllers\PostController; +use App\Http\Controllers\Controller; use Clue\React\SQLite\DatabaseInterface; use Clue\React\SQLite\Result; use GuzzleHttp\Psr7\Response; @@ -15,7 +15,7 @@ use Twig\Loader\ArrayLoader; use function GuzzleHttp\Psr7\str; use function GuzzleHttp\Psr7\stream_for; -class DeleteUsersController extends PostController +class DeleteUsersController extends AdminController { protected $keepConnectionOpen = true; diff --git a/app/Server/Http/Controllers/Admin/ListSitesController.php b/app/Server/Http/Controllers/Admin/ListSitesController.php index ef9f7a6..4447266 100644 --- a/app/Server/Http/Controllers/Admin/ListSitesController.php +++ b/app/Server/Http/Controllers/Admin/ListSitesController.php @@ -3,7 +3,7 @@ namespace App\Server\Http\Controllers\Admin; use App\Contracts\ConnectionManager; -use App\Http\Controllers\PostController; +use App\Http\Controllers\Controller; use App\Server\Configuration; use Clue\React\SQLite\DatabaseInterface; use Clue\React\SQLite\Result; @@ -15,7 +15,7 @@ use Twig\Loader\ArrayLoader; use function GuzzleHttp\Psr7\str; use function GuzzleHttp\Psr7\stream_for; -class ListSitesController extends PostController +class ListSitesController extends AdminController { /** @var ConnectionManager */ protected $connectionManager; diff --git a/app/Server/Http/Controllers/Admin/ListUsersController.php b/app/Server/Http/Controllers/Admin/ListUsersController.php index 4dc365a..c2a490b 100644 --- a/app/Server/Http/Controllers/Admin/ListUsersController.php +++ b/app/Server/Http/Controllers/Admin/ListUsersController.php @@ -2,7 +2,7 @@ namespace App\Server\Http\Controllers\Admin; -use App\Http\Controllers\PostController; +use App\Http\Controllers\Controller; use Clue\React\SQLite\DatabaseInterface; use Clue\React\SQLite\Result; use GuzzleHttp\Psr7\Response; @@ -13,7 +13,7 @@ use Twig\Loader\ArrayLoader; use function GuzzleHttp\Psr7\str; use function GuzzleHttp\Psr7\stream_for; -class ListUsersController extends PostController +class ListUsersController extends AdminController { protected $keepConnectionOpen = true; diff --git a/app/Server/Http/Controllers/Admin/LoginController.php b/app/Server/Http/Controllers/Admin/LoginController.php deleted file mode 100644 index f519aa5..0000000 --- a/app/Server/Http/Controllers/Admin/LoginController.php +++ /dev/null @@ -1,25 +0,0 @@ -send( - respond_html($this->getView('server.login')) - ); - } -} diff --git a/app/Server/Http/Controllers/Admin/RedirectToUsersController.php b/app/Server/Http/Controllers/Admin/RedirectToUsersController.php new file mode 100644 index 0000000..8a16add --- /dev/null +++ b/app/Server/Http/Controllers/Admin/RedirectToUsersController.php @@ -0,0 +1,20 @@ +send(str(new Response(301, [ + 'Location' => '/sites' + ]))); + } +} diff --git a/app/Server/Http/Controllers/Admin/StoreUsersController.php b/app/Server/Http/Controllers/Admin/StoreUsersController.php index 78f3e6f..21beb66 100644 --- a/app/Server/Http/Controllers/Admin/StoreUsersController.php +++ b/app/Server/Http/Controllers/Admin/StoreUsersController.php @@ -2,7 +2,7 @@ namespace App\Server\Http\Controllers\Admin; -use App\Http\Controllers\PostController; +use App\Http\Controllers\Controller; use Clue\React\SQLite\DatabaseInterface; use Clue\React\SQLite\Result; use GuzzleHttp\Psr7\Response; @@ -15,7 +15,7 @@ use Twig\Loader\ArrayLoader; use function GuzzleHttp\Psr7\str; use function GuzzleHttp\Psr7\stream_for; -class StoreUsersController extends PostController +class StoreUsersController extends AdminController { protected $keepConnectionOpen = true; diff --git a/app/Server/Http/Controllers/Admin/VerifyLoginController.php b/app/Server/Http/Controllers/Admin/VerifyLoginController.php deleted file mode 100644 index 26cfc2b..0000000 --- a/app/Server/Http/Controllers/Admin/VerifyLoginController.php +++ /dev/null @@ -1,51 +0,0 @@ -database = $database; - } - - public function handle(Request $request, ConnectionInterface $httpConnection) - { - $this->database->query("SELECT * FROM users WHERE email = :email", ['email' => $request->email]) - ->then(function (Result $result) use ($httpConnection) { - if (!is_null($result->rows)) { - $httpConnection->send( - str(new Response( - 301, - ['Location' => '/users'] - )) - ); - } else { - $httpConnection->send( - str(new Response( - 301, - ['Location' => '/users'] - )) - ); - } - $httpConnection->close(); - }); - } -} diff --git a/app/Server/Http/Controllers/ControlMessageController.php b/app/Server/Http/Controllers/ControlMessageController.php index dd196ac..27e41dc 100644 --- a/app/Server/Http/Controllers/ControlMessageController.php +++ b/app/Server/Http/Controllers/ControlMessageController.php @@ -131,7 +131,7 @@ class ControlMessageController implements MessageComponentInterface { if (! is_null($subdomain)) { $controlConnection = $this->connectionManager->findControlConnectionForSubdomain($subdomain); - if (! is_null($controlConnection) || $subdomain === config('expose.dashboard_subdomain')) { + if (! is_null($controlConnection) || $subdomain === config('expose.admin.subdomain')) { $connection->send(json_encode([ 'event' => 'subdomainTaken', 'data' => [ diff --git a/app/Server/Http/Controllers/TunnelMessageController.php b/app/Server/Http/Controllers/TunnelMessageController.php index 2e7b652..03fcd35 100644 --- a/app/Server/Http/Controllers/TunnelMessageController.php +++ b/app/Server/Http/Controllers/TunnelMessageController.php @@ -3,7 +3,7 @@ namespace App\Server\Http\Controllers; use App\Contracts\ConnectionManager; -use App\Http\Controllers\PostController; +use App\Http\Controllers\Controller; use App\Server\Configuration; use App\Server\Connections\ControlConnection; use GuzzleHttp\Psr7\Response; @@ -16,7 +16,7 @@ use Ratchet\RFC6455\Messaging\Frame; use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; use function GuzzleHttp\Psr7\str; -class TunnelMessageController extends PostController +class TunnelMessageController extends Controller { /** @var ConnectionManager */ protected $connectionManager; diff --git a/app/helpers.php b/app/helpers.php index 827bb1d..376eeac 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -8,7 +8,7 @@ function respond_json($responseData, int $statusCode = 200) return str(new Response( $statusCode, ['Content-Type' => 'application/json'], - json_encode($responseData) + json_encode($responseData, JSON_INVALID_UTF8_IGNORE) )); } diff --git a/config/expose.php b/config/expose.php index 7bcf79a..dd39380 100644 --- a/config/expose.php +++ b/config/expose.php @@ -4,5 +4,33 @@ return [ 'host' => 'expose.dev', 'port' => 8080, 'auth_token' => '', - 'dashboard_subdomain' => 'expose', + + 'admin' => [ + + /* + |-------------------------------------------------------------------------- + | Subdomain + |-------------------------------------------------------------------------- + | + | This is the subdomain that your expose admin dashboard will be available at. + | The given subdomain will be reserved, so no other tunnel connection can + | request this subdomain for their own connection. + | + */ + 'subdomain' => 'expose', + + /* + |-------------------------------------------------------------------------- + | Users + |-------------------------------------------------------------------------- + | + | The admin dashboard of expose is protected via HTTP basic authentication + | Here you may add the user/password combinations that you want to + | accept as valid logins for the dashboard. + | + */ + 'users' => [ + 'username' => 'password' + ] + ] ]; diff --git a/tests/Feature/Client/DashboardTest.php b/tests/Feature/Client/DashboardTest.php index 9d9355c..e163740 100755 --- a/tests/Feature/Client/DashboardTest.php +++ b/tests/Feature/Client/DashboardTest.php @@ -15,6 +15,7 @@ use Psr\Http\Message\ResponseInterface; use React\EventLoop\LoopInterface; use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Tests\Feature\TestCase; use function GuzzleHttp\Psr7\str; class DashboardTest extends TestCase diff --git a/tests/Feature/Server/AdminTest.php b/tests/Feature/Server/AdminTest.php new file mode 100644 index 0000000..6a82edc --- /dev/null +++ b/tests/Feature/Server/AdminTest.php @@ -0,0 +1,8 @@ +