mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-08 00:02:15 +01:00
Moved force https logic to a middleware; Changed default for config session.secure
This commit is contained in:
committed by
Constantin Graf
parent
adf0d35c11
commit
d924fa74ec
1
.env.ci
1
.env.ci
@@ -5,7 +5,6 @@ APP_DEBUG=true
|
|||||||
APP_URL=http://localhost
|
APP_URL=http://localhost
|
||||||
APP_FORCE_HTTPS=false
|
APP_FORCE_HTTPS=false
|
||||||
APP_ENABLE_REGISTRATION=true
|
APP_ENABLE_REGISTRATION=true
|
||||||
SESSION_SECURE_COOKIE=false
|
|
||||||
|
|
||||||
# Logging
|
# Logging
|
||||||
LOG_CHANNEL=stack
|
LOG_CHANNEL=stack
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ VITE_APP_NAME=solidtime
|
|||||||
APP_ENV=production
|
APP_ENV=production
|
||||||
APP_DEBUG=false
|
APP_DEBUG=false
|
||||||
APP_FORCE_HTTPS=true
|
APP_FORCE_HTTPS=true
|
||||||
SESSION_SECURE_COOKIE=true
|
|
||||||
OCTANE_SERVER=frankenphp
|
OCTANE_SERVER=frankenphp
|
||||||
PAGINATION_PER_PAGE_DEFAULT=500
|
PAGINATION_PER_PAGE_DEFAULT=500
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ class UserResource extends Resource
|
|||||||
{
|
{
|
||||||
/** @var User|null $record */
|
/** @var User|null $record */
|
||||||
$record = $form->getRecord();
|
$record = $form->getRecord();
|
||||||
|
|
||||||
return $form
|
return $form
|
||||||
->columns(1)
|
->columns(1)
|
||||||
->schema([
|
->schema([
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ class HealthCheckController extends Controller
|
|||||||
$response['app_env'] = app()->environment();
|
$response['app_env'] = app()->environment();
|
||||||
$response['app_timezone'] = config('app.timezone');
|
$response['app_timezone'] = config('app.timezone');
|
||||||
$response['app_force_https'] = config('app.force_https');
|
$response['app_force_https'] = config('app.force_https');
|
||||||
|
$response['session_secure'] = config('session.secure');
|
||||||
$response['trusted_proxies'] = config('trustedproxy.proxies');
|
$response['trusted_proxies'] = config('trustedproxy.proxies');
|
||||||
$headers = $request->headers->all();
|
$headers = $request->headers->all();
|
||||||
if (isset($headers['cookie'])) {
|
if (isset($headers['cookie'])) {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class Kernel extends HttpKernel
|
|||||||
* @var array<int, class-string|string>
|
* @var array<int, class-string|string>
|
||||||
*/
|
*/
|
||||||
protected $middleware = [
|
protected $middleware = [
|
||||||
// \App\Http\Middleware\TrustHosts::class,
|
\App\Http\Middleware\ForceHttps::class,
|
||||||
\App\Http\Middleware\TrustProxies::class,
|
\App\Http\Middleware\TrustProxies::class,
|
||||||
\Illuminate\Http\Middleware\HandleCors::class,
|
\Illuminate\Http\Middleware\HandleCors::class,
|
||||||
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
|
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
|
||||||
|
|||||||
29
app/Http/Middleware/ForceHttps.php
Normal file
29
app/Http/Middleware/ForceHttps.php
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\URL;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class ForceHttps
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handle an incoming request.
|
||||||
|
*
|
||||||
|
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||||||
|
*/
|
||||||
|
public function handle(Request $request, Closure $next, string ...$guards): Response
|
||||||
|
{
|
||||||
|
if (config('app.force_https', false)) {
|
||||||
|
URL::forceScheme('https');
|
||||||
|
$request->server->set('HTTPS', 'on');
|
||||||
|
$request->headers->set('X-Forwarded-Proto', 'https');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace App\Http\Middleware;
|
|
||||||
|
|
||||||
use Illuminate\Http\Middleware\TrustHosts as Middleware;
|
|
||||||
|
|
||||||
class TrustHosts extends Middleware
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Get the host patterns that should be trusted.
|
|
||||||
*
|
|
||||||
* @return array<int, string|null>
|
|
||||||
*/
|
|
||||||
public function hosts(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
$this->allSubdomainsOfApplicationUrl(),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -29,7 +29,6 @@ use Illuminate\Database\Eloquent\Model;
|
|||||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||||
use Illuminate\Foundation\Application;
|
use Illuminate\Foundation\Application;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use Illuminate\Support\Facades\URL;
|
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
|
||||||
class AppServiceProvider extends ServiceProvider
|
class AppServiceProvider extends ServiceProvider
|
||||||
@@ -90,12 +89,6 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (config('app.force_https', false)) {
|
|
||||||
URL::forceScheme('https');
|
|
||||||
request()->server->set('HTTPS', 'on');
|
|
||||||
request()->headers->set('X-Forwarded-Proto', 'https');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->app->scoped(PermissionStore::class, function (Application $app): PermissionStore {
|
$this->app->scoped(PermissionStore::class, function (Application $app): PermissionStore {
|
||||||
return new PermissionStore;
|
return new PermissionStore;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ return [
|
|||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'secure' => env('SESSION_SECURE_COOKIE'),
|
'secure' => env('SESSION_SECURE_COOKIE', env('APP_FORCE_HTTPS')),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -29,6 +29,8 @@
|
|||||||
</source>
|
</source>
|
||||||
<php>
|
<php>
|
||||||
<env name="APP_ENV" value="testing"/>
|
<env name="APP_ENV" value="testing"/>
|
||||||
|
<env name="APP_FORCE_HTTPS" value="false"/>
|
||||||
|
<env name="TRUSTED_PROXIES" value="0.0.0.0/0,2000:0:0:0:0:0:0:0/3"/>
|
||||||
<env name="BCRYPT_ROUNDS" value="4"/>
|
<env name="BCRYPT_ROUNDS" value="4"/>
|
||||||
<env name="CACHE_DRIVER" value="array"/>
|
<env name="CACHE_DRIVER" value="array"/>
|
||||||
<env name="DB_CONNECTION" value="pgsql_test"/>
|
<env name="DB_CONNECTION" value="pgsql_test"/>
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ class HealthCheckEndpointTest extends EndpointTestAbstract
|
|||||||
'secure',
|
'secure',
|
||||||
'timestamp',
|
'timestamp',
|
||||||
'timezone',
|
'timezone',
|
||||||
|
'session_secure',
|
||||||
'trusted_proxies',
|
'trusted_proxies',
|
||||||
'url',
|
'url',
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -5,11 +5,15 @@ declare(strict_types=1);
|
|||||||
namespace Tests\Unit\Endpoint\Web;
|
namespace Tests\Unit\Endpoint\Web;
|
||||||
|
|
||||||
use App\Http\Controllers\Web\HomeController;
|
use App\Http\Controllers\Web\HomeController;
|
||||||
|
use App\Http\Middleware\Authenticate;
|
||||||
|
use App\Http\Middleware\RedirectIfAuthenticated;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use PHPUnit\Framework\Attributes\CoversClass;
|
use PHPUnit\Framework\Attributes\CoversClass;
|
||||||
use PHPUnit\Framework\Attributes\UsesClass;
|
use PHPUnit\Framework\Attributes\UsesClass;
|
||||||
|
|
||||||
#[CoversClass(HomeController::class)]
|
#[CoversClass(HomeController::class)]
|
||||||
|
#[CoversClass(Authenticate::class)]
|
||||||
|
#[CoversClass(RedirectIfAuthenticated::class)]
|
||||||
#[UsesClass(HomeController::class)]
|
#[UsesClass(HomeController::class)]
|
||||||
class HomeEndpointTest extends EndpointTestAbstract
|
class HomeEndpointTest extends EndpointTestAbstract
|
||||||
{
|
{
|
||||||
@@ -36,4 +40,17 @@ class HomeEndpointTest extends EndpointTestAbstract
|
|||||||
// Assert
|
// Assert
|
||||||
$response->assertRedirect('/login');
|
$response->assertRedirect('/login');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_login_redirects_to_dashboard_if_user_is_logged_in(): void
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
$user = User::factory()->withPersonalOrganization()->create();
|
||||||
|
$this->actingAs($user);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
$response = $this->get('/login');
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
$response->assertRedirect('/dashboard');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,20 @@ class EnsureEmailIsVerifiedMiddlewareTest extends MiddlewareTestAbstract
|
|||||||
$response->assertRedirect(route('verification.notice'));
|
$response->assertRedirect(route('verification.notice'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_users_with_unverified_email_get_error_if_the_request_is_json(): void
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
$user = User::factory()->unverified()->create();
|
||||||
|
$route = $this->createTestRoute();
|
||||||
|
$this->actingAs($user);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
$response = $this->getJson($route);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
$response->assertForbidden();
|
||||||
|
}
|
||||||
|
|
||||||
public function test_users_with_verified_email_can_access_route(): void
|
public function test_users_with_verified_email_can_access_route(): void
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
|
|||||||
81
tests/Unit/Middleware/ForceHttpsMiddlewareTest.php
Normal file
81
tests/Unit/Middleware/ForceHttpsMiddlewareTest.php
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Tests\Unit\Middleware;
|
||||||
|
|
||||||
|
use App\Http\Middleware\ForceHttps;
|
||||||
|
use Illuminate\Support\Facades\Config;
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
use PHPUnit\Framework\Attributes\CoversClass;
|
||||||
|
use PHPUnit\Framework\Attributes\UsesClass;
|
||||||
|
|
||||||
|
#[CoversClass(ForceHttps::class)]
|
||||||
|
#[UsesClass(ForceHttps::class)]
|
||||||
|
class ForceHttpsMiddlewareTest extends MiddlewareTestAbstract
|
||||||
|
{
|
||||||
|
private function createTestRoute(): string
|
||||||
|
{
|
||||||
|
return Route::get('/test-route', function () {
|
||||||
|
return [
|
||||||
|
'is_secure' => request()->secure(),
|
||||||
|
];
|
||||||
|
})->middleware(ForceHttps::class)->uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_if_config_app_force_https_is_true_then_the_request_will_be_modified_to_make_the_app_think_it_was_a_https_request(): void
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
Config::set('app.force_https', true);
|
||||||
|
$route = $this->createTestRoute();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
$response = $this->get($route);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
$response->assertSuccessful();
|
||||||
|
$response->assertJson(['is_secure' => true]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_if_config_app_force_https_is_true_then_the_request_will_be_modified_to_make_the_app_think_it_was_a_https_request_even_if_a_load_balancer_says_it_was_a_http_request(): void
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
Config::set('app.force_https', true);
|
||||||
|
$route = $this->createTestRoute();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
$response = $this->get($route, ['X-Forwarded-Proto' => 'http']);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
$response->assertSuccessful();
|
||||||
|
$response->assertJson(['is_secure' => true]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_if_config_app_force_https_is_false_then_the_request_will_not_be_modified_to_make_the_app_think_it_was_a_https_request(): void
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
Config::set('app.force_https', false);
|
||||||
|
$route = $this->createTestRoute();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
$response = $this->get($route);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
$response->assertSuccessful();
|
||||||
|
$response->assertJson(['is_secure' => false]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_if_config_app_force_https_is_false_then_the_request_will_not_be_modified_but_the_request_can_still_be_https(): void
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
Config::set('app.force_https', false);
|
||||||
|
$route = $this->createTestRoute();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
$response = $this->get($route, ['X-Forwarded-Proto' => 'https']);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
$response->assertSuccessful();
|
||||||
|
$response->assertJson(['is_secure' => true]);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user