From a024093e8c40a3421c622c33872f6ec8cd19b283 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 1 Feb 2026 01:51:01 +0200 Subject: [PATCH] Fix npm build permissions for public assets --- VERSION | 2 +- .../Commands/Jabali/UpgradeCommand.php | 28 +++++++++++++++++++ tests/Unit/UpgradeCommandTest.php | 1 + 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 7ed0dac..4871c45 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -VERSION=0.9-rc36 +VERSION=0.9-rc37 diff --git a/app/Console/Commands/Jabali/UpgradeCommand.php b/app/Console/Commands/Jabali/UpgradeCommand.php index 200cc49..688d7c6 100644 --- a/app/Console/Commands/Jabali/UpgradeCommand.php +++ b/app/Console/Commands/Jabali/UpgradeCommand.php @@ -186,6 +186,7 @@ class UpgradeCommand extends Command $this->ensureCommandAvailable('npm'); $this->ensureNpmCacheDirectory(); $this->ensureNodeModulesPermissions(); + $this->ensurePublicBuildPermissions(); if (! $this->isNodeModulesWritable()) { $this->warn('Skipping frontend build because node_modules is not writable by the current user.'); $this->warn('Run: sudo chown -R www-data:www-data '.$this->getNodeModulesPath()); @@ -208,6 +209,7 @@ class UpgradeCommand extends Command } $this->ensureNodeModulesPermissions(); + $this->ensurePublicBuildPermissions(); } } catch (Exception $e) { $this->error('Asset build failed: '.$e->getMessage()); @@ -437,6 +439,7 @@ class UpgradeCommand extends Command $this->basePath.'/database', $this->basePath.'/storage', $this->getNodeModulesPath(), + $this->getPublicBuildPath(), $this->getNpmCacheDir(), $this->getPuppeteerCacheDir(), $this->getXdgCacheDir(), @@ -494,6 +497,26 @@ class UpgradeCommand extends Command $this->executeCommand('chmod -R u+rwX '.escapeshellarg($nodeModules)); } + protected function ensurePublicBuildPermissions(): void + { + $buildPath = $this->getPublicBuildPath(); + + if (! File::exists($buildPath)) { + File::ensureDirectoryExists($buildPath); + } + + if ($this->isRunningAsRoot() && $this->userExists('www-data')) { + $escaped = escapeshellarg($buildPath); + $this->executeCommand("chgrp -R www-data {$escaped}"); + $this->executeCommand("chmod -R g+rwX {$escaped}"); + $this->executeCommand("find {$escaped} -type d -exec chmod g+s {} +"); + + return; + } + + $this->executeCommand('chmod -R u+rwX '.escapeshellarg($buildPath)); + } + protected function isNodeModulesWritable(): bool { $nodeModules = $this->getNodeModulesPath(); @@ -524,6 +547,11 @@ class UpgradeCommand extends Command return $this->basePath.'/node_modules'; } + protected function getPublicBuildPath(): string + { + return $this->basePath.'/public/build'; + } + protected function getPuppeteerCacheDir(): string { return $this->basePath.'/storage/puppeteer-cache'; diff --git a/tests/Unit/UpgradeCommandTest.php b/tests/Unit/UpgradeCommandTest.php index 4622887..105eb1d 100644 --- a/tests/Unit/UpgradeCommandTest.php +++ b/tests/Unit/UpgradeCommandTest.php @@ -133,6 +133,7 @@ class UpgradeCommandTest extends TestCase base_path().'/database', base_path().'/storage', base_path().'/node_modules', + base_path().'/public/build', base_path().'/storage/npm-cache', base_path().'/storage/puppeteer-cache', base_path().'/storage/.cache',