From 3ce56b5206f71cd78aff68150c0c02cf03aed8a6 Mon Sep 17 00:00:00 2001 From: James Cole Date: Tue, 7 Jul 2026 11:09:05 +0200 Subject: [PATCH] Catch access issues in installer. --- app/Http/Controllers/Controller.php | 7 +++ .../Controllers/System/InstallController.php | 51 ++++++++++--------- app/Http/Middleware/Installer.php | 8 +-- app/Support/AppConfiguration.php | 5 +- app/Support/System/IsOldVersion.php | 28 ++++++---- 5 files changed, 57 insertions(+), 42 deletions(-) diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 34f5934236..9fe629642b 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers; use FireflyIII\Events\Model\Webhook\WebhookMessagesRequestSending; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Support\Facades\Amount; use FireflyIII\Support\Facades\AppConfiguration; @@ -72,7 +73,13 @@ abstract class Controller extends BaseController public function __construct() { // is site a demo site? + try { $isDemoSiteConfig = AppConfiguration::get('is_demo_site', config('firefly.configuration.is_demo_site', false)); + } catch(FireflyException $e) { + // if this breaks, just stop right here. + Log::error($e->getMessage()); + return; + } $isDemoSite = (bool) $isDemoSiteConfig->data; View::share('IS_DEMO_SITE', $isDemoSite); View::share('DEMO_USERNAME', config('firefly.demo_username')); diff --git a/app/Http/Controllers/System/InstallController.php b/app/Http/Controllers/System/InstallController.php index d80e452291..6f705715ac 100644 --- a/app/Http/Controllers/System/InstallController.php +++ b/app/Http/Controllers/System/InstallController.php @@ -41,7 +41,6 @@ use Illuminate\Support\Facades\Log; use Illuminate\View\View; use Laravel\Passport\Passport; use phpseclib3\Crypt\RSA; - use function Safe\file_put_contents; /** @@ -56,33 +55,37 @@ final class InstallController extends Controller public const string FORBIDDEN_ERROR = 'Internal PHP function "proc_close" is disabled for your installation. Auto-migration is not possible.'; public const string OTHER_ERROR = 'An unknown error prevented Firefly III from executing the upgrade commands. Sorry.'; - private string $lastError = ''; + private string $lastError = ''; // empty on purpose. - private array $upgradeCommands = [ - // there are 5 initial commands - // Check 4 places: InstallController, Docker image, UpgradeDatabase, composer.json - 'firefly-iii:create-database' => [], - 'migrate' => ['--seed' => true, '--force' => true], - 'generate-keys' => [], // an exception :( - 'firefly-iii:upgrade-database' => [], - 'firefly-iii:set-latest-version' => ['--james-is-cool' => true], - 'firefly-iii:verify-security-alerts' => [], - ]; + private array $upgradeCommands + = [ + // there are 5 initial commands + // Check 4 places: InstallController, Docker image, UpgradeDatabase, composer.json + 'firefly-iii:create-database' => [], + 'migrate' => ['--seed' => true, '--force' => true], + 'generate-keys' => [], // an exception :( + 'firefly-iii:upgrade-database' => [], + 'firefly-iii:set-latest-version' => ['--james-is-cool' => true], + 'firefly-iii:verify-security-alerts' => [], + ]; /** * Show index. * * @return Factory|View */ - public function index(): Factory|\Illuminate\Contracts\View\View + public function index(): Factory | \Illuminate\Contracts\View\View { if ($this->hasNoTables() || $this->isOldVersionInstalled()) { app('view')->share('FF_VERSION', config('firefly.version')); // index will set FF3 version. - AppConfiguration::set('ff3_version', (string) config('firefly.version')); - AppConfiguration::set('ff3_build_time', (int) config('firefly.build_time')); - + try { + AppConfiguration::set('ff3_version', (string)config('firefly.version')); + AppConfiguration::set('ff3_build_time', (int)config('firefly.build_time')); + } catch (FireflyException $e) { + Log::warning($e->getMessage()); + } return view('install.index'); } @@ -94,8 +97,8 @@ final class InstallController extends Controller */ public function keys(): void { - if (!$this->hasNoTables() && !$this->isOldVersionInstalled()) { - $key = RSA::createKey(4096); + if ($this->hasNoTables() || $this->isOldVersionInstalled()) { + $key = RSA::createKey(4096); [$publicKey, $privateKey] = [Passport::keyPath('oauth-public.key'), Passport::keyPath('oauth-private.key')]; @@ -103,22 +106,22 @@ final class InstallController extends Controller return; } - file_put_contents($publicKey, (string) $key->getPublicKey()); + file_put_contents($publicKey, (string)$key->getPublicKey()); file_put_contents($privateKey, $key->toString('PKCS1')); } } public function runCommand(Request $request): JsonResponse { - if (!$this->hasNoTables() && !$this->isOldVersionInstalled()) { - $requestIndex = (int) $request->input('index'); + if ($this->hasNoTables() || $this->isOldVersionInstalled()) { + $requestIndex = (int)$request->input('index'); $response = ['hasNextCommand' => false, 'done' => true, 'previous' => null, 'error' => false, 'errorMessage' => null]; Log::debug(sprintf('Will now run commands. Request index is %d', $requestIndex)); - $indexes = array_keys($this->upgradeCommands); + $indexes = array_keys($this->upgradeCommands); if (array_key_exists($requestIndex, $indexes)) { - $command = $indexes[$requestIndex]; - $parameters = $this->upgradeCommands[$command]; + $command = $indexes[$requestIndex]; + $parameters = $this->upgradeCommands[$command]; Log::debug(sprintf('Will now execute command "%s" with parameters', $command), $parameters); try { diff --git a/app/Http/Middleware/Installer.php b/app/Http/Middleware/Installer.php index 128374f419..31f1dc579a 100644 --- a/app/Http/Middleware/Installer.php +++ b/app/Http/Middleware/Installer.php @@ -75,11 +75,5 @@ class Installer return $next($request); } - /** - * Is access denied error. - */ - protected function isAccessDenied(string $message): bool - { - return false !== stripos($message, 'Access denied'); - } + } diff --git a/app/Support/AppConfiguration.php b/app/Support/AppConfiguration.php index efcacddb34..6345872719 100644 --- a/app/Support/AppConfiguration.php +++ b/app/Support/AppConfiguration.php @@ -61,7 +61,7 @@ class AppConfiguration try { /** @var null|Configuration $config */ $config = Configuration::query()->where('name', $name)->first(['id', 'name', 'data']); - } catch (Exception|QueryException $e) { + } catch (Exception|QueryException|FireflyException $e) { throw new FireflyException(sprintf('Could not poll the database: %s', $e->getMessage()), 0, $e); } @@ -128,6 +128,9 @@ class AppConfiguration return $this->set($name, $value); } + /** + * @throws FireflyException + */ public function set(string $name, mixed $value): Configuration { try { diff --git a/app/Support/System/IsOldVersion.php b/app/Support/System/IsOldVersion.php index 388e5473a8..d83816574e 100644 --- a/app/Support/System/IsOldVersion.php +++ b/app/Support/System/IsOldVersion.php @@ -47,8 +47,8 @@ trait IsOldVersion return 0; } - $currentDate = Carbon::createFromFormat('!Y-m-d', $currentParts[1]); - $latestDate = Carbon::createFromFormat('!Y-m-d', $latestParts[1]); + $currentDate = Carbon::createFromFormat('!Y-m-d', $currentParts[1]); + $latestDate = Carbon::createFromFormat('!Y-m-d', $latestParts[1]); if ($currentDate->lt($latestDate)) { Log::debug(sprintf('This current version is older, current = %s, latest version %s.', $current, $latest)); @@ -71,16 +71,16 @@ trait IsOldVersion protected function isOldVersionInstalled(): bool { // version compare thing. - $configBuildTime = (int) config('firefly.build_time'); - $dbBuildTime = (int) AppConfiguration::getFresh('ff3_build_time', 123)->data; + $configBuildTime = (int)config('firefly.build_time'); + $dbBuildTime = (int)AppConfiguration::getFresh('ff3_build_time', 123)->data; $configTime = Carbon::createFromTimestamp($configBuildTime, config('app.timezone')); $dbTime = Carbon::createFromTimestamp($dbBuildTime, config('app.timezone')); if ($dbBuildTime < $configBuildTime) { Log::warning(sprintf( - 'Your database was last managed by an older version of Firefly III (I see %s, I expect %s). Redirect to migrate routine.', - $dbTime->format('Y-m-d H:i:s'), - $configTime->format('Y-m-d H:i:s') - )); + 'Your database was last managed by an older version of Firefly III (I see %s, I expect %s). Redirect to migrate routine.', + $dbTime->format('Y-m-d H:i:s'), + $configTime->format('Y-m-d H:i:s') + )); return true; } @@ -104,7 +104,7 @@ trait IsOldVersion */ private function hasNoTables(): bool { - // Log::debug('Now in routine hasNoTables()'); + Log::debug('Now in routine hasNoTables()'); try { DB::table('users')->count(); @@ -128,8 +128,16 @@ trait IsOldVersion throw new FireflyException(sprintf('Could not access the database: %s', $message), 0, $e); } - // Log::debug('Everything seems OK with the tables.'); + Log::debug('Everything seems OK with the tables.'); return false; } + + /** + * Is access denied error. + */ + private function isAccessDenied(string $message): bool + { + return false !== stripos($message, 'Access denied'); + } }