From 25ac83e944af6eea329dbf15aec1a3a54379598d Mon Sep 17 00:00:00 2001 From: Andras Kovacs Date: Mon, 26 May 2025 13:07:51 +0200 Subject: [PATCH 01/21] Bumped container image versions --- dev.docker-compose.yml | 4 ++-- docker-compose.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dev.docker-compose.yml b/dev.docker-compose.yml index 6cf4a1e2f2..0cd8139c0e 100644 --- a/dev.docker-compose.yml +++ b/dev.docker-compose.yml @@ -21,7 +21,7 @@ services: - .env.dev.docker mariadb: - image: mariadb:11.5.2 + image: mariadb:11.4.7 volumes: - db:/var/lib/mysql env_file: @@ -36,7 +36,7 @@ services: retries: 5 redis: - image: redis:7.4.0 + image: redis:7.4.3 mailhog: image: mailhog/mailhog:v1.0.1 diff --git a/docker-compose.yml b/docker-compose.yml index d5e9b3ae89..d874d2e008 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -20,7 +20,7 @@ services: - .env db: - image: mariadb:11.5.2 + image: mariadb:11.4.7 restart: unless-stopped volumes: - db_data:/var/lib/mysql From 93b760d53be0197ab6e1e1a0e4becb313198d16c Mon Sep 17 00:00:00 2001 From: snipe Date: Mon, 2 Jun 2025 22:16:36 +0100 Subject: [PATCH 02/21] Disable form fields if the value is blank Signed-off-by: snipe --- resources/views/hardware/bulk-checkout.blade.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/resources/views/hardware/bulk-checkout.blade.php b/resources/views/hardware/bulk-checkout.blade.php index 6a1cbacf6a..69be1f3b61 100644 --- a/resources/views/hardware/bulk-checkout.blade.php +++ b/resources/views/hardware/bulk-checkout.blade.php @@ -137,6 +137,14 @@ //if there's already a user selected, make sure their checked-out assets show up // (if there isn't one, it won't do anything) $('#assigned_user').change(); + + // Add the disabled attribute to empty inputs on submit to handle the case where someone does not pick a status ID + // and the form is submitted with an empty status ID which will fail validation via the form request + $("form").submit(function() { + $(this).find(":input").filter(function(){ return !this.value; }).attr("disabled", "disabled"); + return true; // ensure form still submits + }); + }); From 55cf5877c465fa817b53f1912f55d8c3d19ff5f7 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 3 Jun 2025 05:28:45 +0100 Subject: [PATCH 03/21] Updated tests Signed-off-by: snipe --- .../Assets/Ui/BulkDeleteAssetsTest.php | 4 +++ tests/Feature/Assets/Ui/DeleteAssetTest.php | 27 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/tests/Feature/Assets/Ui/BulkDeleteAssetsTest.php b/tests/Feature/Assets/Ui/BulkDeleteAssetsTest.php index 747028e5e1..ec8ed33ba8 100644 --- a/tests/Feature/Assets/Ui/BulkDeleteAssetsTest.php +++ b/tests/Feature/Assets/Ui/BulkDeleteAssetsTest.php @@ -137,6 +137,10 @@ class BulkDeleteAssetsTest extends TestCase 'item_type' => Asset::class, ] ); + + $asset->refresh(); + $this->assertNull($asset->assigned_to); + $this->assertNull($asset->assigned_type); } public function testActionLogCreatedUponBulkRestore() diff --git a/tests/Feature/Assets/Ui/DeleteAssetTest.php b/tests/Feature/Assets/Ui/DeleteAssetTest.php index a12e9e2cd0..799643929b 100644 --- a/tests/Feature/Assets/Ui/DeleteAssetTest.php +++ b/tests/Feature/Assets/Ui/DeleteAssetTest.php @@ -48,6 +48,29 @@ class DeleteAssetTest extends TestCase ]); } + public function testActionLogsActionDateIsPopulatedWhenAssetDeleted() + { + $actor = User::factory()->deleteAssets()->create(); + + $asset = Asset::factory()->create(); + + $this->actingAs($actor)->delete(route('hardware.destroy', $asset)); + + $asset->refresh(); + + $this->assertDatabaseHas('action_logs', [ + 'action_date' => $asset->updated_at, + 'created_at' => $asset->updated_at, + 'created_by' => $actor->id, + 'action_type' => 'delete', + 'target_id' => null, + 'target_type' => null, + 'item_type' => Asset::class, + 'item_id' => $asset->id, + ]); + + } + public function testAssetIsCheckedInWhenDeleted() { Event::fake(); @@ -65,6 +88,10 @@ class DeleteAssetTest extends TestCase 'Asset still assigned to user after deletion' ); + $asset->refresh(); + $this->assertNull($asset->assigned_to); + $this->assertNull($asset->assigned_type); + Event::assertDispatched(CheckoutableCheckedIn::class); } From 3d8f8faf0111bcbc876cf79083d4844e283897c1 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 3 Jun 2025 05:28:58 +0100 Subject: [PATCH 04/21] Added action_date Signed-off-by: snipe --- app/Observers/AssetObserver.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/Observers/AssetObserver.php b/app/Observers/AssetObserver.php index 9f31f3c231..2db5a5a8c7 100644 --- a/app/Observers/AssetObserver.php +++ b/app/Observers/AssetObserver.php @@ -62,6 +62,7 @@ class AssetObserver $logAction = new Actionlog(); $logAction->item_type = Asset::class; $logAction->item_id = $asset->id; + $logAction->action_date = date('Y-m-d H:i:s'); $logAction->created_at = date('Y-m-d H:i:s'); $logAction->created_by = auth()->id(); $logAction->log_meta = json_encode($changed); @@ -108,6 +109,7 @@ class AssetObserver $logAction = new Actionlog(); $logAction->item_type = Asset::class; // can we instead say $logAction->item = $asset ? $logAction->item_id = $asset->id; + $logAction->action_date = date('Y-m-d H:i:s'); $logAction->created_at = date('Y-m-d H:i:s'); $logAction->created_by = auth()->id(); if($asset->imported) { @@ -124,10 +126,12 @@ class AssetObserver */ public function deleting(Asset $asset) { + \Log::error('deleting observer fired for asset: ' . $asset->id); $logAction = new Actionlog(); $logAction->item_type = Asset::class; $logAction->item_id = $asset->id; $logAction->created_at = date('Y-m-d H:i:s'); + $logAction->action_date = date('Y-m-d H:i:s'); $logAction->created_by = auth()->id(); $logAction->logaction('delete'); } @@ -143,6 +147,7 @@ class AssetObserver $logAction = new Actionlog(); $logAction->item_type = Asset::class; $logAction->item_id = $asset->id; + $logAction->action_date = date('Y-m-d H:i:s'); $logAction->created_at = date('Y-m-d H:i:s'); $logAction->created_by = auth()->id(); $logAction->logaction('restore'); From a7bb8907292f615c197a2770989368acad59ee54 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 3 Jun 2025 05:29:49 +0100 Subject: [PATCH 05/21] Removed action date from array of things to log Signed-off-by: snipe --- app/Models/Loggable.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/Models/Loggable.php b/app/Models/Loggable.php index 4cf5817668..b86dc1cf94 100644 --- a/app/Models/Loggable.php +++ b/app/Models/Loggable.php @@ -95,7 +95,7 @@ trait Loggable $changed = []; $array_to_flip = array_keys($fields_array); - $array_to_flip = array_merge($array_to_flip, ['action_date','name','status_id','location_id','expected_checkin']); + $array_to_flip = array_merge($array_to_flip, ['name','status_id','location_id','expected_checkin']); $originalValues = array_intersect_key($originalValues, array_flip($array_to_flip)); @@ -182,7 +182,7 @@ trait Loggable $log->note = $note; $log->action_date = $action_date; - if (! $log->action_date) { + if (!$action_date) { $log->action_date = date('Y-m-d H:i:s'); } @@ -193,7 +193,7 @@ trait Loggable $changed = []; $array_to_flip = array_keys($fields_array); - $array_to_flip = array_merge($array_to_flip, ['action_date','name','status_id','location_id','expected_checkin']); + $array_to_flip = array_merge($array_to_flip, ['name','status_id','location_id','expected_checkin']); $originalValues = array_intersect_key($originalValues, array_flip($array_to_flip)); From 550e2b6bb8f59a4131d789a77cece5e6debf20ff Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 3 Jun 2025 05:30:30 +0100 Subject: [PATCH 06/21] Null both assigned to and assigned type on delete Signed-off-by: snipe --- app/Http/Controllers/Assets/AssetsController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/Assets/AssetsController.php b/app/Http/Controllers/Assets/AssetsController.php index e6e6041992..809605bccb 100755 --- a/app/Http/Controllers/Assets/AssetsController.php +++ b/app/Http/Controllers/Assets/AssetsController.php @@ -446,7 +446,7 @@ class AssetsController extends Controller event(new CheckoutableCheckedIn($asset, $target, auth()->user(), 'Checkin on delete', $checkin_at, $originalValues)); DB::table('assets') ->where('id', $asset->id) - ->update(['assigned_to' => null]); + ->update(['assigned_to' => null, 'assigned_type' => null]); } From 45c6406ff40003de487bd2f209491fe1592619ea Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 3 Jun 2025 05:30:43 +0100 Subject: [PATCH 07/21] Added console command for fixup Signed-off-by: snipe --- .../FixUpAssignedTypeWithoutAssignedTo.php | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 app/Console/Commands/FixUpAssignedTypeWithoutAssignedTo.php diff --git a/app/Console/Commands/FixUpAssignedTypeWithoutAssignedTo.php b/app/Console/Commands/FixUpAssignedTypeWithoutAssignedTo.php new file mode 100644 index 0000000000..f368929f16 --- /dev/null +++ b/app/Console/Commands/FixUpAssignedTypeWithoutAssignedTo.php @@ -0,0 +1,32 @@ +whereNotNull('assigned_type')->whereNull('assigned_to')->update(['assigned_type' => null]); + $this->info("Assets with an assigned_type but no assigned_to are fixed"); + } +} From e4ce71ff14e78fa777a25753e058083a3ed95b88 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 3 Jun 2025 05:30:53 +0100 Subject: [PATCH 08/21] Added time on action date Signed-off-by: snipe --- app/Events/CheckoutableCheckedIn.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Events/CheckoutableCheckedIn.php b/app/Events/CheckoutableCheckedIn.php index 48aed2a64d..fedbd49fbe 100644 --- a/app/Events/CheckoutableCheckedIn.php +++ b/app/Events/CheckoutableCheckedIn.php @@ -28,7 +28,7 @@ class CheckoutableCheckedIn $this->checkedOutTo = $checkedOutTo; $this->checkedInBy = $checkedInBy; $this->note = $note; - $this->action_date = $action_date ?? date('Y-m-d'); + $this->action_date = $action_date ?? date('Y-m-d H:i:s'); $this->originalValues = $originalValues; } } From 7c9433be5d7b47fe312fb3a667d869ee0e8902ad Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 3 Jun 2025 05:37:37 +0100 Subject: [PATCH 09/21] Added migration to fix existing wonky data Signed-off-by: snipe --- ..._fix_assigned_type_without_assigned_to.php | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 database/migrations/2025_06_03_053438_fix_assigned_type_without_assigned_to.php diff --git a/database/migrations/2025_06_03_053438_fix_assigned_type_without_assigned_to.php b/database/migrations/2025_06_03_053438_fix_assigned_type_without_assigned_to.php new file mode 100644 index 0000000000..9d6a1c8046 --- /dev/null +++ b/database/migrations/2025_06_03_053438_fix_assigned_type_without_assigned_to.php @@ -0,0 +1,23 @@ +whereNotNull('assigned_type')->whereNull('assigned_to')->update(['assigned_type' => null]); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + + } +}; From 0dfc083a914a72cf832792c8a9067e22138fd196 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 3 Jun 2025 06:07:06 +0100 Subject: [PATCH 10/21] Removed log error Signed-off-by: snipe --- app/Observers/AssetObserver.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/Observers/AssetObserver.php b/app/Observers/AssetObserver.php index 2db5a5a8c7..6c07a355ff 100644 --- a/app/Observers/AssetObserver.php +++ b/app/Observers/AssetObserver.php @@ -126,7 +126,6 @@ class AssetObserver */ public function deleting(Asset $asset) { - \Log::error('deleting observer fired for asset: ' . $asset->id); $logAction = new Actionlog(); $logAction->item_type = Asset::class; $logAction->item_id = $asset->id; From 9eaabf95a00e6b28a2566fb2de298f9e9f35cc87 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 3 Jun 2025 11:02:41 +0100 Subject: [PATCH 11/21] Make version number match tagged version :( Signed-off-by: snipe --- config/version.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/config/version.php b/config/version.php index eb0374337c..9d0b165893 100644 --- a/config/version.php +++ b/config/version.php @@ -1,10 +1,10 @@ 'v8.1.5', - 'full_app_version' => 'v8.1.5 - build 18388-g64aeaeeee', - 'build_version' => '18388', + 'app_version' => 'v8.1.15', + 'full_app_version' => 'v8.1.15 - build 18405-ge4314cf42', + 'build_version' => '18405', 'prerelease_version' => '', - 'hash_version' => 'g64aeaeeee', - 'full_hash' => 'v8.1.5-141-g64aeaeeee', + 'hash_version' => 'ge4314cf42', + 'full_hash' => 'v8.1.15-13-ge4314cf42', 'branch' => 'develop', ); \ No newline at end of file From cb608d7fd16d21e1b24c40a4150ade033f49270b Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Tue, 3 Jun 2025 11:58:57 -0700 Subject: [PATCH 12/21] testing buttons out --- .../models/custom_fields_form_bulk_edit.blade.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/resources/views/models/custom_fields_form_bulk_edit.blade.php b/resources/views/models/custom_fields_form_bulk_edit.blade.php index cea495ccd2..68a42a8006 100644 --- a/resources/views/models/custom_fields_form_bulk_edit.blade.php +++ b/resources/views/models/custom_fields_form_bulk_edit.blade.php @@ -30,6 +30,9 @@ :selected="old($field->db_column_name(),(isset($item) ? Helper::gracefulDecrypt($field, $item->{$field->db_column_name()}) : $field->defaultValue($model->id)))" class="format form-control" /> + @elseif ($field->element=='textarea') @if($field->is_unique) @@ -45,7 +48,9 @@ {$field->db_column_name()}))) ? ' checked="checked"' : '') : (old($field->db_column_name()) != '' ? ' checked="checked"' : (in_array($key, array_map('trim', explode(',', $field->defaultValue($model->id)))) ? ' checked="checked"' : '')) }}> {{ $value }} - + @endforeach @elseif ($field->element=='radio') @foreach ($field->formatFieldValuesAsArray() as $value) @@ -54,7 +59,9 @@ {$field->db_column_name()} == $value ? ' checked="checked"' : '') : (old($field->db_column_name()) != '' ? ' checked="checked"' : (in_array($value, explode(', ', $field->defaultValue($model->id))) ? ' checked="checked"' : '')) }}> {{ $value }} - + @endforeach @endif From dc562d8c20916a97d2f248e2aacdad99417afbf6 Mon Sep 17 00:00:00 2001 From: snipe Date: Wed, 4 Jun 2025 08:43:40 +0100 Subject: [PATCH 13/21] Remove error log Signed-off-by: snipe --- app/Http/Controllers/Assets/BulkAssetsController.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/Http/Controllers/Assets/BulkAssetsController.php b/app/Http/Controllers/Assets/BulkAssetsController.php index 6fc25224f9..338f5b2763 100644 --- a/app/Http/Controllers/Assets/BulkAssetsController.php +++ b/app/Http/Controllers/Assets/BulkAssetsController.php @@ -613,7 +613,6 @@ class BulkAssetsController extends Controller // See if there is a status label passed if ($request->filled('status_id')) { - \Log::error('status id: ' . $request->get('status_id')); $asset->status_id = $request->get('status_id'); } From 3e1f71026c61970b1547545cb3cb6f3c4eed54bb Mon Sep 17 00:00:00 2001 From: snipe Date: Wed, 4 Jun 2025 10:37:04 +0100 Subject: [PATCH 14/21] Fixed #16240 - made additional strings translatable Signed-off-by: snipe --- resources/lang/en-US/general.php | 4 ++++ resources/views/layouts/default.blade.php | 9 ++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/resources/lang/en-US/general.php b/resources/lang/en-US/general.php index 599a15c139..cda9efc221 100644 --- a/resources/lang/en-US/general.php +++ b/resources/lang/en-US/general.php @@ -581,6 +581,10 @@ return [ 'user_managed_passwords_allow' => 'Allow users to manage their own passwords', 'from' => 'From', 'by' => 'By', + 'by_lower' => 'by', + 'version' => 'Version', + 'build' => 'build', + 'footer_credit' => 'Snipe-IT is open source software, made with love by @snipeitapp.com.', // Add form placeholders here 'placeholders' => [ diff --git a/resources/views/layouts/default.blade.php b/resources/views/layouts/default.blade.php index 2dfe860bf1..4175cdf11a 100644 --- a/resources/views/layouts/default.blade.php +++ b/resources/views/layouts/default.blade.php @@ -921,15 +921,14 @@ dir="{{ Helper::determineLanguageDirection() }}">