diff --git a/app/Http/Middleware/EncryptCookies.php b/app/Http/Middleware/EncryptCookies.php index 867695bdcf..66b89002c1 100644 --- a/app/Http/Middleware/EncryptCookies.php +++ b/app/Http/Middleware/EncryptCookies.php @@ -14,4 +14,14 @@ class EncryptCookies extends Middleware protected $except = [ // ]; + + /** + * The remembered list views (RemembersCanvasView) hold only an allow-listed view name. + * Encryption makes each of these per-user, per-page cookies about 330 bytes, and the + * browser sends all of them on the Reverb WebSocket handshake too. + */ + public function isDisabled($name) + { + return parent::isDisabled($name) || preg_match('/^coolify_\d+_[a-z_]+_view$/', $name) === 1; + } } diff --git a/config/reverb.php b/config/reverb.php index 6331511347..e3498baa63 100644 --- a/config/reverb.php +++ b/config/reverb.php @@ -36,7 +36,7 @@ return [ 'options' => [ 'tls' => [], ], - 'max_request_size' => 10_000, + 'max_request_size' => 64_000, 'scaling' => [ 'enabled' => false, 'channel' => 'reverb', diff --git a/tests/Feature/DashboardCanvasTest.php b/tests/Feature/DashboardCanvasTest.php index 9204b3e77a..d020ecffcc 100644 --- a/tests/Feature/DashboardCanvasTest.php +++ b/tests/Feature/DashboardCanvasTest.php @@ -116,17 +116,17 @@ test('the dashboard opens the canvas again when the user left it there', functio ->get(route('dashboard.canvas')) ->assertOk() ->assertSee('data-endpoint="/dashboard/canvas"', false) - ->assertCookie($cookie, 'canvas'); + ->assertPlainCookie($cookie, 'canvas'); dashboardCanvasSession($this, $this->admin, $this->team) - ->withCookie($cookie, 'canvas') + ->withUnencryptedCookie($cookie, 'canvas') ->get(route('dashboard')) ->assertRedirect(route('dashboard.canvas')); // The list link on the canvas opens the list and makes it the remembered view. dashboardCanvasSession($this, $this->admin, $this->team) - ->withCookie($cookie, 'canvas') + ->withUnencryptedCookie($cookie, 'canvas') ->get(route('dashboard', ['view' => 'list'])) ->assertOk() - ->assertCookie($cookie, 'list'); + ->assertPlainCookie($cookie, 'list'); }); diff --git a/tests/Feature/DashboardViewModeTest.php b/tests/Feature/DashboardViewModeTest.php index 008907103e..e810b9ed94 100644 --- a/tests/Feature/DashboardViewModeTest.php +++ b/tests/Feature/DashboardViewModeTest.php @@ -37,7 +37,7 @@ it('remembers the view of each dashboard section on its own', function () { expect(Cookie::queued("coolify_{$this->user->id}_dashboard_projects_view")?->getValue())->toBe('grid') ->and(Cookie::queued("coolify_{$this->user->id}_dashboard_servers_view"))->toBeNull(); - $this->withCookie("coolify_{$this->user->id}_dashboard_projects_view", 'grid') + $this->withUnencryptedCookie("coolify_{$this->user->id}_dashboard_projects_view", 'grid') ->get(route('dashboard')) ->assertOk() ->assertSee("viewMode: 'grid'", false) diff --git a/tests/Feature/ProjectCanvasTest.php b/tests/Feature/ProjectCanvasTest.php index db02a05736..d2efe040dc 100644 --- a/tests/Feature/ProjectCanvasTest.php +++ b/tests/Feature/ProjectCanvasTest.php @@ -134,19 +134,19 @@ test('the project page reopens the canvas when the user left it on the canvas vi ->get(route('project.canvas', $parameters)) ->assertOk() ->assertSee('data-endpoint="/projects/'.$this->project->uuid.'/canvas"', false) - ->assertCookie("coolify_{$this->admin->id}_project_view", 'canvas'); + ->assertPlainCookie("coolify_{$this->admin->id}_project_view", 'canvas'); projectCanvasSession($this, $this->admin, $this->team) - ->withCookie("coolify_{$this->admin->id}_project_view", 'canvas') + ->withUnencryptedCookie("coolify_{$this->admin->id}_project_view", 'canvas') ->get(route('project.show', $parameters)) ->assertRedirect(route('project.canvas', $parameters)); // The table / grid links on the canvas pick the list view again. projectCanvasSession($this, $this->admin, $this->team) - ->withCookie("coolify_{$this->admin->id}_project_view", 'canvas') + ->withUnencryptedCookie("coolify_{$this->admin->id}_project_view", 'canvas') ->get(route('project.show', [...$parameters, 'view' => 'grid'])) ->assertOk() - ->assertCookie("coolify_{$this->admin->id}_project_view", 'grid'); + ->assertPlainCookie("coolify_{$this->admin->id}_project_view", 'grid'); }); test('the projects canvas shows every project of the team as a zone, grouped by environment', function () { @@ -230,18 +230,18 @@ test('the projects page reopens the canvas when the user left it on the canvas v projectCanvasSession($this, $this->admin, $this->team) ->get(route('project.canvas.index')) ->assertOk() - ->assertCookie("coolify_{$this->admin->id}_projects_view", 'canvas'); + ->assertPlainCookie("coolify_{$this->admin->id}_projects_view", 'canvas'); projectCanvasSession($this, $this->admin, $this->team) - ->withCookie("coolify_{$this->admin->id}_projects_view", 'canvas') + ->withUnencryptedCookie("coolify_{$this->admin->id}_projects_view", 'canvas') ->get(route('project.index')) ->assertRedirect(route('project.canvas.index')); projectCanvasSession($this, $this->admin, $this->team) - ->withCookie("coolify_{$this->admin->id}_projects_view", 'canvas') + ->withUnencryptedCookie("coolify_{$this->admin->id}_projects_view", 'canvas') ->get(route('project.index', ['view' => 'table'])) ->assertOk() - ->assertCookie("coolify_{$this->admin->id}_projects_view", 'table'); + ->assertPlainCookie("coolify_{$this->admin->id}_projects_view", 'table'); }); test('an admin creates an environment from the project canvas', function () { diff --git a/tests/Feature/ServerCanvasTest.php b/tests/Feature/ServerCanvasTest.php index a3ec0b4bd0..14c1dcbd5c 100644 --- a/tests/Feature/ServerCanvasTest.php +++ b/tests/Feature/ServerCanvasTest.php @@ -221,22 +221,22 @@ test('the servers page reopens the canvas when the user left it on the canvas vi serverCanvasSession($this, $this->admin, $this->team) ->get(route('server.canvas.index')) ->assertOk() - ->assertCookie("coolify_{$this->admin->id}_servers_view", 'canvas'); + ->assertPlainCookie("coolify_{$this->admin->id}_servers_view", 'canvas'); serverCanvasSession($this, $this->admin, $this->team) - ->withCookie("coolify_{$this->admin->id}_servers_view", 'canvas') + ->withUnencryptedCookie("coolify_{$this->admin->id}_servers_view", 'canvas') ->get(route('server.index')) ->assertRedirect(route('server.canvas.index')); // The table / grid links on the canvas pick the list view again. serverCanvasSession($this, $this->admin, $this->team) - ->withCookie("coolify_{$this->admin->id}_servers_view", 'canvas') + ->withUnencryptedCookie("coolify_{$this->admin->id}_servers_view", 'canvas') ->get(route('server.index', ['view' => 'grid'])) ->assertOk() - ->assertCookie("coolify_{$this->admin->id}_servers_view", 'grid'); + ->assertPlainCookie("coolify_{$this->admin->id}_servers_view", 'grid'); serverCanvasSession($this, $this->admin, $this->team) - ->withCookie("coolify_{$this->admin->id}_servers_view", 'grid') + ->withUnencryptedCookie("coolify_{$this->admin->id}_servers_view", 'grid') ->get(route('server.index')) ->assertOk(); }); @@ -247,18 +247,18 @@ test('the environment page reopens the canvas when the user left it on the canva serverCanvasSession($this, $this->admin, $this->team) ->get(route('project.environment.canvas', $parameters)) ->assertOk() - ->assertCookie("coolify_{$this->admin->id}_environment_view", 'canvas'); + ->assertPlainCookie("coolify_{$this->admin->id}_environment_view", 'canvas'); serverCanvasSession($this, $this->admin, $this->team) - ->withCookie("coolify_{$this->admin->id}_environment_view", 'canvas') + ->withUnencryptedCookie("coolify_{$this->admin->id}_environment_view", 'canvas') ->get(route('project.resource.index', $parameters)) ->assertRedirect(route('project.environment.canvas', $parameters)); serverCanvasSession($this, $this->admin, $this->team) - ->withCookie("coolify_{$this->admin->id}_environment_view", 'canvas') + ->withUnencryptedCookie("coolify_{$this->admin->id}_environment_view", 'canvas') ->get(route('project.resource.index', [...$parameters, 'view' => 'table'])) ->assertOk() - ->assertCookie("coolify_{$this->admin->id}_environment_view", 'table'); + ->assertPlainCookie("coolify_{$this->admin->id}_environment_view", 'table'); }); test('the server resources page reopens the one server canvas when the user left it on the canvas view', function () { @@ -267,18 +267,18 @@ test('the server resources page reopens the one server canvas when the user left serverCanvasSession($this, $this->admin, $this->team) ->get(route('server.canvas', $parameters)) ->assertOk() - ->assertCookie("coolify_{$this->admin->id}_server_resources_view", 'canvas'); + ->assertPlainCookie("coolify_{$this->admin->id}_server_resources_view", 'canvas'); serverCanvasSession($this, $this->admin, $this->team) - ->withCookie("coolify_{$this->admin->id}_server_resources_view", 'canvas') + ->withUnencryptedCookie("coolify_{$this->admin->id}_server_resources_view", 'canvas') ->get(route('server.resources', $parameters)) ->assertRedirect(route('server.canvas', $parameters)); serverCanvasSession($this, $this->admin, $this->team) - ->withCookie("coolify_{$this->admin->id}_server_resources_view", 'canvas') + ->withUnencryptedCookie("coolify_{$this->admin->id}_server_resources_view", 'canvas') ->get(route('server.resources', [...$parameters, 'view' => 'list'])) ->assertOk() - ->assertCookie("coolify_{$this->admin->id}_server_resources_view", 'list'); + ->assertPlainCookie("coolify_{$this->admin->id}_server_resources_view", 'list'); }); test('the canvas API works with the browser session when the instance API is disabled', function () { @@ -295,7 +295,7 @@ test('the remembered view belongs to the user, not to the browser', function () $this->team->members()->attach($other->id, ['role' => 'admin']); serverCanvasSession($this, $other, $this->team) - ->withCookie("coolify_{$this->admin->id}_servers_view", 'canvas') + ->withUnencryptedCookie("coolify_{$this->admin->id}_servers_view", 'canvas') ->get(route('server.index')) ->assertOk(); }); @@ -315,7 +315,7 @@ test('the list page remembers the table or grid choice and opens it again', func expect(Cookie::getQueuedCookies())->toBeEmpty(); serverCanvasSession($this, $this->admin, $this->team) - ->withCookie($cookie, 'grid') + ->withUnencryptedCookie($cookie, 'grid') ->get(route('server.index')) ->assertOk() ->assertSee("viewMode: 'grid'", false); diff --git a/tests/Feature/SharedVariableCanvasTest.php b/tests/Feature/SharedVariableCanvasTest.php index 92b3db0f6c..89b7d5d487 100644 --- a/tests/Feature/SharedVariableCanvasTest.php +++ b/tests/Feature/SharedVariableCanvasTest.php @@ -297,18 +297,18 @@ test('each shared variables page reopens its canvas when the user left it on the sharedVariableCanvasAs($this, $this->admin, $this->team) ->get(route("shared-variables.{$scope}.canvas", $parameters)) ->assertOk() - ->assertCookie($cookie, 'canvas'); + ->assertPlainCookie($cookie, 'canvas'); sharedVariableCanvasAs($this, $this->admin, $this->team) - ->withCookie($cookie, 'canvas') + ->withUnencryptedCookie($cookie, 'canvas') ->get(route($listRoute, $parameters)) ->assertRedirect(route("shared-variables.{$scope}.canvas", $parameters)); sharedVariableCanvasAs($this, $this->admin, $this->team) - ->withCookie($cookie, 'canvas') + ->withUnencryptedCookie($cookie, 'canvas') ->get(route($listRoute, [...$parameters, 'view' => 'list'])) ->assertOk() - ->assertCookie($cookie, 'list'); + ->assertPlainCookie($cookie, 'list'); })->with(['team', 'project', 'environment', 'server']); test('an admin adds a shared variable from the canvas modal and the canvas reloads', function () { diff --git a/tests/Feature/TagCanvasTest.php b/tests/Feature/TagCanvasTest.php index e54af1fcea..88d9b196d5 100644 --- a/tests/Feature/TagCanvasTest.php +++ b/tests/Feature/TagCanvasTest.php @@ -211,16 +211,16 @@ test('the tags page reopens the canvas when the user left it on the canvas view' tagCanvasAs($this, $this->admin, $this->team) ->get(route('tags.canvas')) ->assertOk() - ->assertCookie("coolify_{$this->admin->id}_tags_view", 'canvas'); + ->assertPlainCookie("coolify_{$this->admin->id}_tags_view", 'canvas'); tagCanvasAs($this, $this->admin, $this->team) - ->withCookie("coolify_{$this->admin->id}_tags_view", 'canvas') + ->withUnencryptedCookie("coolify_{$this->admin->id}_tags_view", 'canvas') ->get(route('tags.show')) ->assertRedirect(route('tags.canvas')); tagCanvasAs($this, $this->admin, $this->team) - ->withCookie("coolify_{$this->admin->id}_tags_view", 'canvas') + ->withUnencryptedCookie("coolify_{$this->admin->id}_tags_view", 'canvas') ->get(route('tags.show', ['view' => 'grid'])) ->assertOk() - ->assertCookie("coolify_{$this->admin->id}_tags_view", 'grid'); + ->assertPlainCookie("coolify_{$this->admin->id}_tags_view", 'grid'); });