Compare commits

..

1 Commits

Author SHA1 Message Date
Constantin Graf
45a60a926f Fix docker image 2025-02-07 13:50:56 -05:00
18 changed files with 42 additions and 184 deletions

View File

@@ -5,6 +5,7 @@ APP_DEBUG=true
APP_URL=http://localhost
APP_FORCE_HTTPS=false
APP_ENABLE_REGISTRATION=true
SESSION_SECURE_COOKIE=false
# Logging
LOG_CHANNEL=stack

View File

@@ -5,6 +5,7 @@ VITE_APP_NAME=solidtime
APP_ENV=production
APP_DEBUG=false
APP_FORCE_HTTPS=true
SESSION_SECURE_COOKIE=true
OCTANE_SERVER=frankenphp
PAGINATION_PER_PAGE_DEFAULT=500

View File

@@ -42,7 +42,6 @@ class UserResource extends Resource
{
/** @var User|null $record */
$record = $form->getRecord();
return $form
->columns(1)
->schema([

View File

@@ -64,7 +64,6 @@ class HealthCheckController extends Controller
$response['app_env'] = app()->environment();
$response['app_timezone'] = config('app.timezone');
$response['app_force_https'] = config('app.force_https');
$response['session_secure'] = config('session.secure');
$response['trusted_proxies'] = config('trustedproxy.proxies');
$headers = $request->headers->all();
if (isset($headers['cookie'])) {

View File

@@ -18,7 +18,7 @@ class Kernel extends HttpKernel
* @var array<int, class-string|string>
*/
protected $middleware = [
\App\Http\Middleware\ForceHttps::class,
// \App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\Illuminate\Http\Middleware\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,

View File

@@ -1,29 +0,0 @@
<?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);
}
}

View File

@@ -0,0 +1,22 @@
<?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(),
];
}
}

View File

@@ -29,6 +29,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Foundation\Application;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
@@ -89,6 +90,12 @@ 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 {
return new PermissionStore;
});

View File

@@ -168,7 +168,7 @@ return [
|
*/
'secure' => env('SESSION_SECURE_COOKIE', env('APP_FORCE_HTTPS')),
'secure' => env('SESSION_SECURE_COOKIE'),
/*
|--------------------------------------------------------------------------

View File

@@ -29,8 +29,6 @@
</source>
<php>
<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="CACHE_DRIVER" value="array"/>
<env name="DB_CONNECTION" value="pgsql_test"/>

View File

@@ -129,6 +129,7 @@ function onSelectChange(event: Event) {
:project="timeEntry.project_id"
:enable-estimated-time
:currency="currency"
class="border border-border-primary"
:task="
timeEntry.task_id
"

View File

@@ -119,6 +119,7 @@ function onSelectChange(event: Event) {
:show-badge-border="false"
:project="timeEntry.project_id"
:currency="currency"
class="border border-border-primary"
:enable-estimated-time
:task="
timeEntry.task_id

View File

@@ -103,14 +103,10 @@ function setBillableDefaultForProject() {
}
}
const blockRefocus = ref(false);
function onToggleButtonPress(newState: boolean) {
if (newState) {
emit('startTimer');
if (!blockRefocus.value){
currentTimeEntryDescriptionInput.value?.focus();
}
currentTimeEntryDescriptionInput.value?.focus();
} else {
emit('stopTimer');
}
@@ -133,27 +129,11 @@ function updateTimeEntryDescription() {
const {timeEntries} = storeToRefs(useTimeEntriesStore());
const filteredRecentlyTrackedTimeEntries = computed(() => {
// do not include running time entries
const finishedTimeEntries = timeEntries.value.filter((item) => item.end !== null);
// filter out duplicates based on description, task, project, tags and billable
const nonDuplicateTimeEntries = finishedTimeEntries.filter((item, index, self) => {
return index === self.findIndex((t) => (
t.description === item.description &&
t.task_id === item.task_id &&
t.project_id === item.project_id &&
t.tags.length === item.tags.length &&
t.tags.every((tag) => item.tags.includes(tag)) &&
t.billable === item.billable
));
});
// filter time entries based on current description
return nonDuplicateTimeEntries.filter((item) => {
return timeEntries.value.filter((item) => {
return item.description
?.toLowerCase()
?.includes(tempDescription.value?.toLowerCase()?.trim() || '');
}).slice(0, 5);
}).slice(0, 5);;
});
const showDropdown = ref(false);
@@ -163,14 +143,6 @@ watch(focused, (focused) => {
nextTick(() => {
// make sure the click event on the dropdown does not get interrupted
showDropdown.value = focused
// make sure that the input does not get refocused after the dropdown is closed
if(!focused){
blockRefocus.value = true;
setTimeout(() => {
blockRefocus.value = false;
}, 100);
}
});
});

View File

@@ -30,14 +30,13 @@ const task = computed(() => {
tabindex="-1"
:data-select-id="timeEntry.id"
:class="twMerge('px-2 py-1.5 flex justify-between items-center space-x-2 w-full rounded', props.highlighted && 'bg-card-background-active')">
<span v-if="timeEntry.description !== ''" class="text-sm font-medium">
<span class="text-sm font-medium">
{{
timeEntry.description
timeEntry.description !== ''
? timeEntry.description
: 'No Description'
}}
</span>
<span v-else class="text-sm text-text-tertiary font-medium">
No Description
</span>
<ProjectBadge
ref="projectDropdownTrigger"
:color="project?.color"

View File

@@ -82,7 +82,6 @@ class HealthCheckEndpointTest extends EndpointTestAbstract
'secure',
'timestamp',
'timezone',
'session_secure',
'trusted_proxies',
'url',
]);

View File

@@ -5,15 +5,11 @@ declare(strict_types=1);
namespace Tests\Unit\Endpoint\Web;
use App\Http\Controllers\Web\HomeController;
use App\Http\Middleware\Authenticate;
use App\Http\Middleware\RedirectIfAuthenticated;
use App\Models\User;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\UsesClass;
#[CoversClass(HomeController::class)]
#[CoversClass(Authenticate::class)]
#[CoversClass(RedirectIfAuthenticated::class)]
#[UsesClass(HomeController::class)]
class HomeEndpointTest extends EndpointTestAbstract
{
@@ -40,17 +36,4 @@ class HomeEndpointTest extends EndpointTestAbstract
// Assert
$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');
}
}

View File

@@ -47,20 +47,6 @@ class EnsureEmailIsVerifiedMiddlewareTest extends MiddlewareTestAbstract
$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
{
// Arrange

View File

@@ -1,81 +0,0 @@
<?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]);
}
}