The formatBytes function was used in the view but never defined, causing
a runtime error. This function was needed to display S3 file sizes in
human-readable format (e.g., "1.5 MB" instead of "1572864").
Added formatBytes() helper to bootstrap/helpers/shared.php:
- Converts bytes to human-readable format (B, KB, MB, GB, TB, PB)
- Uses base 1024 for proper binary conversion
- Configurable precision (defaults to 2 decimal places)
- Handles zero bytes case
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit introduces functionality for integrating S3 storage into the import process. It allows users to select S3 storage, check for file existence, and download files directly from S3. This enhancement improves the flexibility of the import feature by enabling users to work with files stored in S3, addressing a common use case for teams that utilize cloud storage solutions.
Changes:
- Added tab character ("\t") to dangerous characters list as token separator
- Removed redundant regex-based preg_match block (lines 147-152)
- Characters $(, ${, and backticks were already covered in $dangerousChars array
- Simplified function to rely solely on $dangerousChars loop
Security improvement:
- Tab characters can act as token separators in shell contexts
- Now explicitly blocked with descriptive error message
Tests:
- Added test for tab character blocking
- All 78 security tests pass (213 assertions)
- No regression in existing functionality
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit addresses a critical security issue where malicious Docker Compose
data was being saved to the database before validation occurred.
Problem:
- Service models were saved to database first
- Validation ran afterwards during parse()
- Malicious data persisted even when validation failed
- User saw error but damage was already done
Solution:
1. Created validateDockerComposeForInjection() to validate YAML before save
2. Added pre-save validation to all Service creation/update points:
- Livewire: DockerCompose.php, StackForm.php
- API: ServicesController.php (create, update, one-click)
3. Validates service names and volume paths (string + array formats)
4. Blocks shell metacharacters: backticks, $(), |, ;, &, >, <, newlines
Security fixes:
- Volume source paths (string format) - validated before save
- Volume source paths (array format) - validated before save
- Service names - validated before save
- Environment variable patterns - safe ${VAR} allowed, ${VAR:-$(cmd)} blocked
Testing:
- 60 security tests pass (176 assertions)
- PreSaveValidationTest.php: 15 tests for pre-save validation
- ValidateShellSafePathTest.php: 15 tests for core validation
- VolumeSecurityTest.php: 15 tests for volume parsing
- ServiceNameSecurityTest.php: 15 tests for service names
Related commits:
- Previous: Added validation during parse() phase
- This commit: Moves validation before database save
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit addresses two critical issues with Docker Compose service management:
## Issue 1: Duplicate Services Created on Image Change
When changing the image in a docker-compose file, the parser was creating new
ServiceApplication/ServiceDatabase records instead of updating existing ones.
**Root Cause**: The parsers used `firstOrCreate()` with `['name', 'image', 'service_id']`,
meaning any image change would create a new record.
**Fix**: Remove `image` from `firstOrCreate()` queries and update it separately after
finding or creating the service record.
**Changes**:
- `bootstrap/helpers/parsers.php` (serviceParser v3): Fixed in presave loop (lines 1188-1203)
and main parsing loop (lines 1519-1539)
- `bootstrap/helpers/shared.php` (parseDockerComposeFile v2): Fixed null check logic
(lines 1308-1348)
## Issue 2: UI Not Refreshing After Changes
When compose file or domain was modified, the Configuration component wasn't receiving
events to refresh its data, requiring manual page refresh to see updates.
**Root Cause**: The Configuration component wasn't listening for refresh events dispatched
by child components (StackForm, EditDomain).
**Fix**: Add event listeners and dispatchers to enable real-time UI updates.
**Changes**:
- `app/Livewire/Project/Service/Configuration.php`: Added listeners for `refreshServices`
and `refresh` events (lines 36-37)
- `app/Livewire/Project/Service/EditDomain.php`: Added `refreshServices` dispatch (line 76)
- Note: `app/Livewire/Project/Service/StackForm.php` already had the dispatch
## Tests Added
- `tests/Unit/ServiceParserImageUpdateTest.php`: 4 tests verifying no duplicates created
- `tests/Unit/ServiceConfigurationRefreshTest.php`: 4 tests verifying event dispatching
All 8 new tests pass, and all existing unit tests continue to pass.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This change introduces automatically generated `SERVICE_NAME_<SERVICE>`
environment variables for each service within a Docker Compose deployment.
This allows services to reliably reference each other by name, which is particularly
useful in pull request environments where container names are dynamically suffixed.
- The application parser now generates and injects these `SERVICE_NAME` variables
into the environment of all services in the compose file.
- `ApplicationDeploymentJob` is updated to correctly handle and filter these
new variables during deployment.
- UI components and the `EnvironmentVariableProtection` trait have been updated
to make these generated variables read-only, preventing accidental modification.
This commit introduces two new helper functions to standardize resource naming
for pull request deployments:
- `addPreviewDeploymentSuffix()`: Generates a consistent suffix format (-pr-{id})
for resource names in preview deployments
- `generateDockerComposeServiceName()`: Creates SERVICE_NAME environment variables
for Docker Compose services
Updated the default Nginx configuration function to enhance clarity and maintainability. Removed unnecessary redirection logic and added explicit handling for 404 errors, ensuring a more robust error management strategy. This refactor simplifies the configuration while maintaining essential functionality, contributing to a cleaner and more efficient setup.
- Removed the private property for application deployment queue ID in ApplicationDeploymentJob and utilized constructor property promotion.
- Added a tags method in ApplicationDeploymentJob to properly identify the worker running the job.
- Updated HorizonServiceProvider to handle cases where the deployment queue ID is blank, preventing potential errors during job processing.
- Cleaned up the isAnyDeploymentInprogress function by removing unnecessary whitespace.
- Simplified the job status retrieval process by consolidating logic into a single `getJobStatus` function.
- Removed redundant checks and methods from the `CustomJobRepositoryInterface` and `CustomJobRepository`.
- Updated the `getHorizonJobStatus` method in `ApplicationDeploymentQueue` to directly utilize the new `getJobStatus` function.
- Enhanced the `isThereAJobInProgress` method to improve clarity and maintainability.
- Updated the isAnyDeploymentInprogress function to check for running jobs based on the current hostname.
- Enhanced the logic to return true if any job status is 'unknown' and to provide a clearer output regarding the number of deployments in progress.
- Modified the cloud_upgrade.sh script to loop until the deployment status check confirms no ongoing deployments before proceeding with the upgrade.