diff --git a/.env.example b/.env.example index 699b6495..c78d9e93 100644 --- a/.env.example +++ b/.env.example @@ -4,7 +4,7 @@ APP_DEBUG=true APP_NAME="InvoiceShelf" APP_LOG_LEVEL=debug APP_TIMEZONE=UTC -APP_URL=http://invoiceshelf.test +APP_URL= APP_LOCALE=en APP_FALLBACK_LOCALE=en @@ -49,7 +49,6 @@ PUSHER_APP_ID= PUSHER_KEY= PUSHER_SECRET= -SANCTUM_STATEFUL_DOMAINS=invoiceshelf.test TRUSTED_PROXIES="*" CRON_JOB_AUTH_TOKEN="" diff --git a/app/Http/Controllers/V1/Installation/DatabaseConfigurationController.php b/app/Http/Controllers/V1/Installation/DatabaseConfigurationController.php index 5c640349..c66cab1c 100644 --- a/app/Http/Controllers/V1/Installation/DatabaseConfigurationController.php +++ b/app/Http/Controllers/V1/Installation/DatabaseConfigurationController.php @@ -29,7 +29,10 @@ class DatabaseConfigurationController extends Controller $results = $this->environmentManager->saveDatabaseVariables($request); if (array_key_exists('success', $results)) { - Artisan::call('key:generate --force'); + // Automatically regenerating the key is disabled to prevent complications in the wizard process. + // This can cause issues with the CSRF token, resulting in "Token Mismatch" or "Invalid CSRF Token" errors. + // It is recommended that the user manually generates the key before running the wizard to ensure application security and stability. + // Artisan::call('key:generate --force'); Artisan::call('optimize:clear'); Artisan::call('config:clear'); Artisan::call('cache:clear'); diff --git a/app/Space/EnvironmentManager.php b/app/Space/EnvironmentManager.php index 05d2cbb5..2e3aea14 100755 --- a/app/Space/EnvironmentManager.php +++ b/app/Space/EnvironmentManager.php @@ -104,14 +104,22 @@ class EnvironmentManager */ public function saveDatabaseVariables(DatabaseEnvironmentRequest $request) { + $appUrl = $request->get('app_url'); + if ($appUrl !== config('app.url')) { + config(['app.url' => $appUrl]); + } + [$sanctumDomain, $sessionDomain] = $this->getDomains( + $request->getHttpHost() + ); $dbEnv = [ - 'APP_URL' => $request->get('app_url'), + 'APP_URL' => $appUrl, 'APP_LOCALE' => $request->get('app_locale'), 'DB_CONNECTION' => $request->get('database_connection'), - 'SANCTUM_STATEFUL_DOMAINS' => $request->get('app_domain'), - 'SESSION_DOMAIN' => explode(':', $request->get('app_domain'))[0], + 'SESSION_DOMAIN' => $sessionDomain, ]; - + if ($sanctumDomain !== null) { + $dbEnv['SANCTUM_STATEFUL_DOMAINS'] = $sanctumDomain; + } if ($dbEnv['DB_CONNECTION'] != 'sqlite') { if ($request->has('database_username') && $request->has('database_password')) { $dbEnv['DB_HOST'] = $request->get('database_hostname'); @@ -462,10 +470,16 @@ class EnvironmentManager public function saveDomainVariables(DomainEnvironmentRequest $request) { try { - $this->updateEnv([ - 'SANCTUM_STATEFUL_DOMAINS' => $request->get('app_domain'), - 'SESSION_DOMAIN' => explode(':', $request->get('app_domain'))[0], - ]); + [$sanctumDomain, $sessionDomain] = $this->getDomains( + $request->get('app_domain') + ); + $domainEnv = [ + 'SESSION_DOMAIN' => $sessionDomain, + ]; + if ($sanctumDomain !== null) { + $domainEnv['SANCTUM_STATEFUL_DOMAINS'] = $sanctumDomain; + } + $this->updateEnv($domainEnv); } catch (Exception $e) { return [ 'error' => 'domain_verification_failed', @@ -505,4 +519,25 @@ class EnvironmentManager file_put_contents($this->envPath, trim($formatted)); } + + private function getDomains(string $requestDomain): array + { + $appUrl = config('app.url'); + + $port = parse_url($appUrl, PHP_URL_PORT); + $currentDomain = parse_url($appUrl, PHP_URL_HOST).( + $port ? ':'.$port : '' + ); + + $requestHost = parse_url($requestDomain, PHP_URL_HOST) ?: $requestDomain; + + $isSame = $currentDomain === $requestDomain; + + return [ + $isSame && env('SANCTUM_STATEFUL_DOMAINS', false) === false ? + null : $requestDomain, + $isSame && env('SESSION_DOMAIN', false) === null ? + null : $requestHost, + ]; + } } diff --git a/composer.lock b/composer.lock index 730429a3..752a47a8 100644 --- a/composer.lock +++ b/composer.lock @@ -12363,4 +12363,4 @@ }, "platform-dev": {}, "plugin-api-version": "2.6.0" -} +} \ No newline at end of file diff --git a/config/sanctum.php b/config/sanctum.php deleted file mode 100644 index 8c94e2a9..00000000 --- a/config/sanctum.php +++ /dev/null @@ -1,48 +0,0 @@ - explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost,127.0.0.1,127.0.0.1:8000,::1')), - - /* - |-------------------------------------------------------------------------- - | Expiration Minutes - |-------------------------------------------------------------------------- - | - | This value controls the number of minutes until an issued token will be - | considered expired. If this value is null, personal access tokens do - | not expire. This won't tweak the lifetime of first-party sessions. - | - */ - - 'expiration' => null, - - /* - |-------------------------------------------------------------------------- - | Sanctum Middleware - |-------------------------------------------------------------------------- - | - | When authenticating your first-party SPA with Sanctum you may need to - | customize some of the middleware Sanctum uses while processing the - | request. You may change the middleware listed below as required. - | - */ - - 'middleware' => [ - 'authenticate_session' => Laravel\Sanctum\Http\Middleware\AuthenticateSession::class, - 'encrypt_cookies' => Illuminate\Cookie\Middleware\EncryptCookies::class, - 'validate_csrf_token' => Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class, - ], - -]; diff --git a/package.json b/package.json index 3f10edc1..b4d8e108 100644 --- a/package.json +++ b/package.json @@ -60,4 +60,4 @@ "vue-router": "^4.5.0", "vuedraggable": "^4.1.0" } -} +} \ No newline at end of file diff --git a/resources/scripts/admin/stores/installation.js b/resources/scripts/admin/stores/installation.js index 4d937df7..8c63fac5 100644 --- a/resources/scripts/admin/stores/installation.js +++ b/resources/scripts/admin/stores/installation.js @@ -185,7 +185,7 @@ export const useInstallationStore = (useWindow = false) => { }) }, - checkAutheticated() { + checkAuthenticated() { return new Promise((resolve, reject) => { axios .get(`/api/v1/auth/check`) diff --git a/resources/scripts/admin/views/installation/Step4VerifyDomain.vue b/resources/scripts/admin/views/installation/Step4VerifyDomain.vue index ec48d085..e4eee4be 100644 --- a/resources/scripts/admin/views/installation/Step4VerifyDomain.vue +++ b/resources/scripts/admin/views/installation/Step4VerifyDomain.vue @@ -87,7 +87,7 @@ async function verifyDomain() { try { await installationStore.setInstallationDomain(formData) await installationStore.installationLogin() - let driverRes = await installationStore.checkAutheticated() + let driverRes = await installationStore.checkAuthenticated() if (driverRes.data) { emit('next', 4) diff --git a/resources/scripts/admin/views/installation/database/MysqlDatabase.vue b/resources/scripts/admin/views/installation/database/MysqlDatabase.vue index 60d309b8..a0b422f8 100644 --- a/resources/scripts/admin/views/installation/database/MysqlDatabase.vue +++ b/resources/scripts/admin/views/installation/database/MysqlDatabase.vue @@ -1,6 +1,6 @@