diff --git a/.github/workflows/tests-mysql.yml b/.github/workflows/tests-mysql.yml
index 737a86dca3e9..310414cda68a 100644
--- a/.github/workflows/tests-mysql.yml
+++ b/.github/workflows/tests-mysql.yml
@@ -76,4 +76,4 @@ jobs:
DB_DATABASE: snipeit
DB_PORT: ${{ job.services.mysql.ports[3306] }}
DB_USERNAME: root
- run: php artisan test --parallel
+ run: php artisan test
diff --git a/.github/workflows/tests-postgres.yml b/.github/workflows/tests-postgres.yml
index 0c361511b8a0..ae48277be3e3 100644
--- a/.github/workflows/tests-postgres.yml
+++ b/.github/workflows/tests-postgres.yml
@@ -74,4 +74,4 @@ jobs:
DB_PORT: ${{ job.services.postgresql.ports[5432] }}
DB_USERNAME: snipeit
DB_PASSWORD: password
- run: php artisan test --parallel
+ run: php artisan test
diff --git a/.github/workflows/tests-sqlite.yml b/.github/workflows/tests-sqlite.yml
index 49c7c92d8e4a..8bf0115169fb 100644
--- a/.github/workflows/tests-sqlite.yml
+++ b/.github/workflows/tests-sqlite.yml
@@ -58,4 +58,4 @@ jobs:
- name: Execute tests (Unit and Feature tests) via PHPUnit
env:
DB_CONNECTION: sqlite_testing
- run: php artisan test --parallel
+ run: php artisan test
diff --git a/app/Http/Controllers/Api/UsersController.php b/app/Http/Controllers/Api/UsersController.php
index 4714b29ea3e9..a9c8c26f14ca 100644
--- a/app/Http/Controllers/Api/UsersController.php
+++ b/app/Http/Controllers/Api/UsersController.php
@@ -14,6 +14,7 @@
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\Accessory;
+use App\Models\Company;
use App\Models\Consumable;
use App\Models\License;
use App\Models\User;
@@ -371,6 +372,7 @@ public function store(SaveUserRequest $request) : JsonResponse
$user = new User;
$user->fill($request->all());
+ $user->company_id = Company::getIdForCurrentUser($request->input('company_id'));
$user->created_by = auth()->id();
if ($request->has('permissions')) {
@@ -452,6 +454,10 @@ public function update(SaveUserRequest $request, User $user): JsonResponse
$user->fill($request->all());
+ if ($request->filled('company_id')) {
+ $user->company_id = Company::getIdForCurrentUser($request->input('company_id'));
+ }
+
if ($user->id == $request->input('manager_id')) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot be your own manager'));
}
diff --git a/app/Http/Controllers/Assets/BulkAssetsController.php b/app/Http/Controllers/Assets/BulkAssetsController.php
index 1ce08e65e9af..c27cfe3e0c69 100644
--- a/app/Http/Controllers/Assets/BulkAssetsController.php
+++ b/app/Http/Controllers/Assets/BulkAssetsController.php
@@ -52,6 +52,10 @@ public function edit(Request $request) : View | RedirectResponse
}
$asset_ids = $request->input('ids');
+ if ($request->input('bulk_actions') === 'checkout') {
+ $request->session()->flashInput(['selected_assets' => $asset_ids]);
+ return redirect()->route('hardware.bulkcheckout.show');
+ }
// Figure out where we need to send the user after the update is complete, and store that in the session
$bulk_back_url = request()->headers->get('referer');
@@ -571,31 +575,34 @@ public function storeCheckout(AssetCheckoutRequest $request) : RedirectResponse
}
$errors = [];
- DB::transaction(function () use ($target, $admin, $checkout_at, $expected_checkin, $errors, $asset_ids, $request) {
+ DB::transaction(function () use ($target, $admin, $checkout_at, $expected_checkin, &$errors, $asset_ids, $request) { //NOTE: $errors is passsed by reference!
foreach ($asset_ids as $asset_id) {
$asset = Asset::findOrFail($asset_id);
$this->authorize('checkout', $asset);
- $error = $asset->checkOut($target, $admin, $checkout_at, $expected_checkin, e($request->get('note')), $asset->name, null);
+ $checkout_success = $asset->checkOut($target, $admin, $checkout_at, $expected_checkin, e($request->get('note')), $asset->name, null);
+ //TODO - I think this logic is duplicated in the checkOut method?
if ($target->location_id != '') {
$asset->location_id = $target->location_id;
- $asset->unsetEventDispatcher();
- $asset->save();
+ // TODO - I don't know why this is being saved without events
+ $asset::withoutEvents(function () use ($asset) {
+ $asset->save();
+ });
}
- if ($error) {
- array_merge_recursive($errors, $asset->getErrors()->toArray());
+ if (!$checkout_success) {
+ $errors = array_merge_recursive($errors, $asset->getErrors()->toArray());
}
}
});
if (! $errors) {
// Redirect to the new asset page
- return redirect()->to('hardware')->with('success', trans('admin/hardware/message.checkout.success'));
+ return redirect()->to('hardware')->with('success', trans_choice('admin/hardware/message.multi-checkout.success', $asset_ids));
}
// Redirect to the asset management page with error
- return redirect()->route('hardware.bulkcheckout.show')->with('error', trans('admin/hardware/message.checkout.error'))->withErrors($errors);
+ return redirect()->route('hardware.bulkcheckout.show')->withInput()->with('error', trans_choice('admin/hardware/message.multi-checkout.error', $asset_ids))->withErrors($errors);
} catch (ModelNotFoundException $e) {
return redirect()->route('hardware.bulkcheckout.show')->with('error', $e->getErrors());
}
diff --git a/app/Http/Transformers/ActionlogsTransformer.php b/app/Http/Transformers/ActionlogsTransformer.php
index 49eee4241575..4e6341c8f33f 100644
--- a/app/Http/Transformers/ActionlogsTransformer.php
+++ b/app/Http/Transformers/ActionlogsTransformer.php
@@ -141,6 +141,8 @@ public function transformActionlog (Actionlog $actionlog, $settings = null)
if ($actionlog->item) {
if ($actionlog->itemType() == 'asset') {
$file_url = route('show/assetfile', ['assetId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
+ } elseif ($actionlog->itemType() == 'accessory') {
+ $file_url = route('show.accessoryfile', ['accessoryId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
} elseif ($actionlog->itemType() == 'license') {
$file_url = route('show.licensefile', ['licenseId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
} elseif ($actionlog->itemType() == 'user') {
@@ -345,4 +347,4 @@ public function changedInfo(array $clean_meta)
-}
\ No newline at end of file
+}
diff --git a/app/Models/CompanyableTrait.php b/app/Models/CompanyableTrait.php
index df67f2be4fa4..04a620d8e3d5 100644
--- a/app/Models/CompanyableTrait.php
+++ b/app/Models/CompanyableTrait.php
@@ -8,9 +8,6 @@ trait CompanyableTrait
* This trait is used to scope models to the current company. To use this scope on companyable models,
* we use the "use Companyable;" statement at the top of the mode.
*
- * We CANNOT USE THIS ON USERS, as it causes an infinite loop and prevents users from logging in, since this scope will be
- * applied to the currently logged in (or logging in) user in addition to the user model for viewing lists of users.
- *
* @see \App\Models\Company\Company::scopeCompanyables()
* @return void
*/
diff --git a/composer.json b/composer.json
index 6d893125787c..d3637c3a4b13 100644
--- a/composer.json
+++ b/composer.json
@@ -74,7 +74,6 @@
"ext-exif": "*"
},
"require-dev": {
- "brianium/paratest": "^7.0",
"fakerphp/faker": "^1.16",
"larastan/larastan": "^2.9",
"mockery/mockery": "^1.4",
diff --git a/composer.lock b/composer.lock
index 3f79921b26df..0631fc275e29 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "3819ab4ef72eb77fabe494c0e746b83b",
+ "content-hash": "5341bc5be02b3c33e28e46e06dd99f29",
"packages": [
{
"name": "alek13/slack",
@@ -11790,101 +11790,6 @@
],
"time": "2024-04-13T18:00:56+00:00"
},
- {
- "name": "brianium/paratest",
- "version": "v7.3.1",
- "source": {
- "type": "git",
- "url": "https://github.com/paratestphp/paratest.git",
- "reference": "551f46f52a93177d873f3be08a1649ae886b4a30"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/paratestphp/paratest/zipball/551f46f52a93177d873f3be08a1649ae886b4a30",
- "reference": "551f46f52a93177d873f3be08a1649ae886b4a30",
- "shasum": ""
- },
- "require": {
- "ext-dom": "*",
- "ext-pcre": "*",
- "ext-reflection": "*",
- "ext-simplexml": "*",
- "fidry/cpu-core-counter": "^0.5.1 || ^1.0.0",
- "jean85/pretty-package-versions": "^2.0.5",
- "php": "~8.1.0 || ~8.2.0 || ~8.3.0",
- "phpunit/php-code-coverage": "^10.1.7",
- "phpunit/php-file-iterator": "^4.1.0",
- "phpunit/php-timer": "^6.0",
- "phpunit/phpunit": "^10.4.2",
- "sebastian/environment": "^6.0.1",
- "symfony/console": "^6.3.4 || ^7.0.0",
- "symfony/process": "^6.3.4 || ^7.0.0"
- },
- "require-dev": {
- "doctrine/coding-standard": "^12.0.0",
- "ext-pcov": "*",
- "ext-posix": "*",
- "infection/infection": "^0.27.6",
- "phpstan/phpstan": "^1.10.40",
- "phpstan/phpstan-deprecation-rules": "^1.1.4",
- "phpstan/phpstan-phpunit": "^1.3.15",
- "phpstan/phpstan-strict-rules": "^1.5.2",
- "squizlabs/php_codesniffer": "^3.7.2",
- "symfony/filesystem": "^6.3.1 || ^7.0.0"
- },
- "bin": [
- "bin/paratest",
- "bin/paratest.bat",
- "bin/paratest_for_phpstorm"
- ],
- "type": "library",
- "autoload": {
- "psr-4": {
- "ParaTest\\": [
- "src/"
- ]
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Brian Scaturro",
- "email": "scaturrob@gmail.com",
- "role": "Developer"
- },
- {
- "name": "Filippo Tessarotto",
- "email": "zoeslam@gmail.com",
- "role": "Developer"
- }
- ],
- "description": "Parallel testing for PHP",
- "homepage": "https://github.com/paratestphp/paratest",
- "keywords": [
- "concurrent",
- "parallel",
- "phpunit",
- "testing"
- ],
- "support": {
- "issues": "https://github.com/paratestphp/paratest/issues",
- "source": "https://github.com/paratestphp/paratest/tree/v7.3.1"
- },
- "funding": [
- {
- "url": "https://github.com/sponsors/Slamdunk",
- "type": "github"
- },
- {
- "url": "https://paypal.me/filippotessarotto",
- "type": "paypal"
- }
- ],
- "time": "2023-10-31T09:24:17+00:00"
- },
{
"name": "clue/ndjson-react",
"version": "v1.3.0",
@@ -12781,65 +12686,6 @@
},
"time": "2020-07-09T08:09:16+00:00"
},
- {
- "name": "jean85/pretty-package-versions",
- "version": "2.0.6",
- "source": {
- "type": "git",
- "url": "https://github.com/Jean85/pretty-package-versions.git",
- "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/f9fdd29ad8e6d024f52678b570e5593759b550b4",
- "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4",
- "shasum": ""
- },
- "require": {
- "composer-runtime-api": "^2.0.0",
- "php": "^7.1|^8.0"
- },
- "require-dev": {
- "friendsofphp/php-cs-fixer": "^3.2",
- "jean85/composer-provided-replaced-stub-package": "^1.0",
- "phpstan/phpstan": "^1.4",
- "phpunit/phpunit": "^7.5|^8.5|^9.4",
- "vimeo/psalm": "^4.3"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Jean85\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Alessandro Lai",
- "email": "alessandro.lai85@gmail.com"
- }
- ],
- "description": "A library to get pretty versions strings of installed dependencies",
- "keywords": [
- "composer",
- "package",
- "release",
- "versions"
- ],
- "support": {
- "issues": "https://github.com/Jean85/pretty-package-versions/issues",
- "source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.6"
- },
- "time": "2024-03-08T09:58:59+00:00"
- },
{
"name": "justinrainbow/json-schema",
"version": "5.3.0",
diff --git a/resources/lang/en-US/admin/hardware/message.php b/resources/lang/en-US/admin/hardware/message.php
index 041d32f56c90..27877e02f9fc 100644
--- a/resources/lang/en-US/admin/hardware/message.php
+++ b/resources/lang/en-US/admin/hardware/message.php
@@ -79,6 +79,11 @@
'no_assets_selected' => 'You must select at least one asset from the list',
],
+ 'multi-checkout' => [
+ 'error' => 'Asset was not checked out, please try again|Assets were not checked out, please try again',
+ 'success' => 'Asset checked out successfully.|Assets checked out successfully.',
+ ],
+
'checkin' => [
'error' => 'Asset was not checked in, please try again',
'success' => 'Asset checked in successfully.',
diff --git a/resources/views/accessories/view.blade.php b/resources/views/accessories/view.blade.php
index e3f98bf61a85..4dc8802e8da2 100644
--- a/resources/views/accessories/view.blade.php
+++ b/resources/views/accessories/view.blade.php
@@ -161,7 +161,6 @@ class="table table-striped snipe-table"
showfile_routename="show.accessoryfile"
deletefile_routename="delete/accessoryfile"
:object="$accessory" />
-
diff --git a/resources/views/hardware/bulk-checkout.blade.php b/resources/views/hardware/bulk-checkout.blade.php
index 405e5e47cd26..39e2cdf10cbf 100644
--- a/resources/views/hardware/bulk-checkout.blade.php
+++ b/resources/views/hardware/bulk-checkout.blade.php
@@ -115,5 +115,12 @@
@section('moar_scripts')
@include('partials/assets-assigned')
+
@stop
diff --git a/resources/views/partials/asset-bulk-actions.blade.php b/resources/views/partials/asset-bulk-actions.blade.php
index b597ad647f78..992fb52bba10 100644
--- a/resources/views/partials/asset-bulk-actions.blade.php
+++ b/resources/views/partials/asset-bulk-actions.blade.php
@@ -16,17 +16,20 @@
diff --git a/tests/Unit/BladeComponents/IconComponentTest.php b/tests/Unit/BladeComponents/IconComponentTest.php
new file mode 100644
index 000000000000..b418b38384ff
--- /dev/null
+++ b/tests/Unit/BladeComponents/IconComponentTest.php
@@ -0,0 +1,20 @@
+ 'checkout'])->render();
+
+ $this->assertFalse(
+ Str::endsWith($renderedTemplateString, PHP_EOL),
+ 'Newline found at end of icon component. Bootstrap tables will not render if there is a newline at the end of the file.'
+ );
+ }
+}