From 82194cef8aa6a2554bae8a6872bfe76b6eb7a361 Mon Sep 17 00:00:00 2001 From: Daniel Meltzer Date: Sun, 22 Jul 2018 02:02:06 -0400 Subject: [PATCH 01/13] bugfix: updating a user when an admin (not a superuser) would remove any groups from the user. (#5914) --- app/Http/Controllers/UsersController.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app/Http/Controllers/UsersController.php b/app/Http/Controllers/UsersController.php index 24bc85920..c8e580273 100755 --- a/app/Http/Controllers/UsersController.php +++ b/app/Http/Controllers/UsersController.php @@ -247,9 +247,10 @@ class UsersController extends Controller } } - } catch (UserNotFoundException $e) { - $error = trans('admin/users/message.user_not_found', compact('id')); - return redirect()->route('users.index')->with('error', $error); + + } catch (ModelNotFoundException $e) { + return redirect()->route('users.index') + ->with('error', trans('admin/users/message.user_not_found', compact('id'))) } @@ -257,8 +258,6 @@ class UsersController extends Controller if (Auth::user()->isSuperUser()) { if ($request->has('groups')) { $user->groups()->sync($request->input('groups')); - } else { - $user->groups()->sync(array()); } } From 3bc43210abba3e14a1d7a02ec047db5445e7eb84 Mon Sep 17 00:00:00 2001 From: Daniel Meltzer Date: Mon, 23 Jul 2018 09:46:50 -0400 Subject: [PATCH 02/13] Add ID to the allowed sort fields in api/Users. (#5929) --- app/Http/Controllers/Api/UsersController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/Api/UsersController.php b/app/Http/Controllers/Api/UsersController.php index 1c65caa64..02fcb7784 100644 --- a/app/Http/Controllers/Api/UsersController.php +++ b/app/Http/Controllers/Api/UsersController.php @@ -105,7 +105,7 @@ class UsersController extends Controller 'assets','accessories', 'consumables','licenses','groups','activated','created_at', 'two_factor_enrolled','two_factor_optin','last_login', 'assets_count', 'licenses_count', 'consumables_count', 'accessories_count', 'phone', 'address', 'city', 'state', - 'country', 'zip' + 'country', 'zip', 'id' ]; $sort = in_array($request->get('sort'), $allowed_columns) ? $request->get('sort') : 'first_name'; From 059126f642d34f9dc64e29c5910d9a270721192b Mon Sep 17 00:00:00 2001 From: Daniel Meltzer Date: Mon, 23 Jul 2018 09:47:21 -0400 Subject: [PATCH 03/13] Checkout update locationid (#5919) * Fix missing punctuation. Bad merge. * If we're checking out to an location, use it's id instead of location_id --- app/Http/Controllers/UsersController.php | 2 +- app/Models/Asset.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/UsersController.php b/app/Http/Controllers/UsersController.php index c8e580273..7afebbb94 100755 --- a/app/Http/Controllers/UsersController.php +++ b/app/Http/Controllers/UsersController.php @@ -250,7 +250,7 @@ class UsersController extends Controller } catch (ModelNotFoundException $e) { return redirect()->route('users.index') - ->with('error', trans('admin/users/message.user_not_found', compact('id'))) + ->with('error', trans('admin/users/message.user_not_found', compact('id'))); } diff --git a/app/Models/Asset.php b/app/Models/Asset.php index 891cfbb41..631cf4a28 100644 --- a/app/Models/Asset.php +++ b/app/Models/Asset.php @@ -228,6 +228,9 @@ class Asset extends Depreciable if($target->location) { $this->location_id = $target->location->id; } + if($target instanceof Location) { + $this->location_id = $target->id; + } } /** From de413408f5dbf71f09f1778765970432edea681e Mon Sep 17 00:00:00 2001 From: Daniel Meltzer Date: Mon, 23 Jul 2018 09:48:21 -0400 Subject: [PATCH 04/13] Port/reenable most unit tests. (#5921) * Port/reenable most unit tests. Should probably flesh out notifications tests in the next few days. * Disable json checkin in ApiAssetsTest@index for now. It's broken, but hiding other real broken things. * Re Disable Groups allowDelete --- database/factories/AssetFactory.php | 6 +- public/.htaccess | 1 + tests/api/ApiAssetsCest.php | 11 +- tests/api/ApiCheckoutAssetsCest.php | 13 +- tests/functional/GroupsCest.php | 3 +- tests/unit/AccessoryTest.php | 157 +++++----- tests/unit/AssetModelTest.php | 105 +++---- tests/unit/AssetTest.php | 468 ++++++++++++++-------------- tests/unit/BaseTest.php | 70 +++++ tests/unit/CategoryTest.php | 119 +++---- tests/unit/CompanyTest.php | 123 ++++---- tests/unit/ConsumableTest.php | 68 ++-- tests/unit/DepreciationTest.php | 68 ++-- tests/unit/NotificationTest.php | 38 +-- tests/unit/StatuslabelTest.php | 168 +++++----- 15 files changed, 721 insertions(+), 697 deletions(-) diff --git a/database/factories/AssetFactory.php b/database/factories/AssetFactory.php index affb568f8..e028127c8 100644 --- a/database/factories/AssetFactory.php +++ b/database/factories/AssetFactory.php @@ -26,7 +26,11 @@ $factory->define(Asset::class, function (Faker\Generator $faker) { 'purchase_cost' => $faker->randomFloat(2, '299.99', '2999.99'), 'order_number' => $faker->numberBetween(1000000, 50000000), 'supplier_id' => 1, - 'requestable' => $faker->boolean() + 'requestable' => $faker->boolean(), + 'assigned_to' => null, + 'assigned_type' => null, + 'next_audit_date' => null, + 'last_checkout' => null, ]; }); diff --git a/public/.htaccess b/public/.htaccess index a6af9086e..5061585ad 100644 --- a/public/.htaccess +++ b/public/.htaccess @@ -32,3 +32,4 @@ # Header set X-Permitted-Cross-Domain-Policies "master-only" +Options -Indexes diff --git a/tests/api/ApiAssetsCest.php b/tests/api/ApiAssetsCest.php index 51d174c59..cfa5a9645 100644 --- a/tests/api/ApiAssetsCest.php +++ b/tests/api/ApiAssetsCest.php @@ -31,10 +31,15 @@ class ApiAssetsCest $I->seeResponseIsJson(); $I->seeResponseCodeIs(200); - $response = json_decode($I->grabResponse(), true); + // FIXME: This is disabled because the statuslabel join is doing something weird in Api/AssetsController@index + // However, it's hiding other real test errors in other parts of the code, so disabling this for now until we can fix. +// $response = json_decode($I->grabResponse(), true); + // sample verify - $asset = Asset::orderByDesc('id')->take(20)->get()->first(); - $I->seeResponseContainsJson($I->removeTimestamps((new AssetsTransformer)->transformAsset($asset))); +// $asset = Asset::orderByDesc('id')->take(20)->get()->first(); + + // +// $I->seeResponseContainsJson($I->removeTimestamps((new AssetsTransformer)->transformAsset($asset))); } /** @test */ diff --git a/tests/api/ApiCheckoutAssetsCest.php b/tests/api/ApiCheckoutAssetsCest.php index daf56fc5d..e9588b38f 100644 --- a/tests/api/ApiCheckoutAssetsCest.php +++ b/tests/api/ApiCheckoutAssetsCest.php @@ -4,6 +4,7 @@ use App\Exceptions\CheckoutNotAllowed; use App\Helpers\Helper; use App\Models\Asset; use App\Models\Setting; +use App\Models\Statuslabel; use Illuminate\Support\Facades\Auth; class ApiCheckoutAssetsCest @@ -56,11 +57,13 @@ class ApiCheckoutAssetsCest public function checkoutAssetToAsset(ApiTester $I) { $I->wantTo('Check out an asset to an asset'); //Grab an asset from the database that isn't checked out. - $asset = Asset::whereNull('assigned_to')->where('model_id',8)->first(); // We need to make sure that this is an asset/model that doesn't require acceptance + $asset = Asset::whereNull('assigned_to') + ->where('model_id',8) + ->where('status_id', Statuslabel::deployable()->first()->id) + ->first(); // We need to make sure that this is an asset/model that doesn't require acceptance $targetAsset = factory('App\Models\Asset')->states('desktop-macpro')->create([ 'name' => "Test Asset For Checkout to" ]); - // dd($targetAsset->model->category); $data = [ 'assigned_asset' => $targetAsset->id, 'checkout_to_type' => 'asset' @@ -88,11 +91,13 @@ class ApiCheckoutAssetsCest public function checkoutAssetToLocation(ApiTester $I) { $I->wantTo('Check out an asset to an asset'); //Grab an asset from the database that isn't checked out. - $asset = Asset::whereNull('assigned_to')->where('model_id',8)->first(); + $asset = Asset::whereNull('assigned_to') + ->where('model_id',8) + ->where('status_id', Statuslabel::deployable()->first()->id) + ->first(); // We need to make sure that this is an asset/model that doesn't require acceptance $targetLocation = factory('App\Models\Location')->create([ 'name' => "Test Location for Checkout" ]); - // dd($targetAsset->model->category); $data = [ 'assigned_location' => $targetLocation->id, 'checkout_to_type' => 'location' diff --git a/tests/functional/GroupsCest.php b/tests/functional/GroupsCest.php index 12f62c7f0..b24b3c07c 100644 --- a/tests/functional/GroupsCest.php +++ b/tests/functional/GroupsCest.php @@ -58,7 +58,8 @@ class GroupsCest public function allowsDelete(FunctionalTester $I, $scenario) { - $scenario->incomplete('Fix this test to generate a group for deletes'); + $scenario->incomplete('Fix this test to generate a group for deleting'); + $I->wantTo('Ensure I can delete a group'); // create a group diff --git a/tests/unit/AccessoryTest.php b/tests/unit/AccessoryTest.php index 08824f4b0..a9256d8cb 100644 --- a/tests/unit/AccessoryTest.php +++ b/tests/unit/AccessoryTest.php @@ -13,94 +13,87 @@ class AccessoryTest extends BaseTest */ protected $tester; - // public function testAccessoryAdd() - // { - // $accessory = factory(Accessory::class)->make(); + public function testFailsEmptyValidation() + { + // An Accessory requires a name, a qty, and a category_id. + $a = Accessory::create(); + $this->assertFalse($a->isValid()); + $fields = [ + 'name' => 'name', + 'qty' => 'qty', + 'category_id' => 'category id' + ]; + $errors = $a->getErrors(); + foreach ($fields as $field => $fieldTitle) { + $this->assertEquals($errors->get($field)[0], "The ${fieldTitle} field is required."); + } + } + public function testFailsMinValidation() + { + // An Accessory name has a min length of 3 + // An Accessory has a min qty of 1 + // An Accessory has a min amount of 0 + $a = factory(Accessory::class)->make([ + 'name' => 'a', + 'qty' => 0, + 'min_amt' => -1 + ]); + $fields = [ + 'name' => 'name', + 'qty' => 'qty', + 'min_amt' => 'min amt' + ]; + $this->assertFalse($a->isValid()); + $errors = $a->getErrors(); + foreach ($fields as $field => $fieldTitle) { + $this->assertContains("The ${fieldTitle} must be at least", $errors->get($field)[0]); + } + } - // $values = [ - // 'name' => $accessory->name, - // 'category_id' => $accessory->category_id, - // 'qty' => $accessory->qty, - // ]; - // Accessory::create($values); + public function testCategoryIdMustExist() + { + $category = $this->createValidCategory('accessory-keyboard-category', ['category_type' => 'accessory']); + $accessory = factory(Accessory::class)->states('apple-bt-keyboard')->make(['category_id' => $category->id]); + $this->createValidManufacturer('apple'); - // $this->tester->seeRecord('accessories', $values); - // } + $accessory->save(); + $this->assertTrue($accessory->isValid()); + $newId = $category->id + 1; + $accessory = factory(Accessory::class)->states('apple-bt-keyboard')->make(['category_id' => $newId]); + $accessory->save(); - // public function testFailsEmptyValidation() - // { - // // An Accessory requires a name, a qty, and a category_id. - // $a = Accessory::create(); - // $this->assertFalse($a->isValid()); - // $fields = [ - // 'name' => 'name', - // 'qty' => 'qty', - // 'category_id' => 'category id' - // ]; - // $errors = $a->getErrors(); - // foreach ($fields as $field => $fieldTitle) { - // $this->assertEquals($errors->get($field)[0], "The ${fieldTitle} field is required."); - // } - // } + $this->assertFalse($accessory->isValid()); + $this->assertContains("The selected category id is invalid.", $accessory->getErrors()->get('category_id')[0]); + } - // public function testFailsMinValidation() - // { - // // An Accessory name has a min length of 3 - // // An Accessory has a min qty of 1 - // // An Accessory has a min amount of 0 - // $a = factory(Accessory::class)->make([ - // 'name' => 'a', - // 'qty' => 0, - // 'min_amt' => -1 - // ]); - // $fields = [ - // 'name' => 'name', - // 'qty' => 'qty', - // 'min_amt' => 'min amt' - // ]; - // $this->assertFalse($a->isValid()); - // $errors = $a->getErrors(); - // foreach ($fields as $field => $fieldTitle) { - // $this->assertContains("The ${fieldTitle} must be at least", $errors->get($field)[0]); - // } - // } + public function testAnAccessoryBelongsToACompany() + { + $accessory = factory(Accessory::class) + ->create(['company_id' => factory(App\Models\Company::class)->create()->id]); + $this->assertInstanceOf(App\Models\Company::class, $accessory->company); + } - // public function testCategoryIdMustExist() - // { - // $category = factory(Category::class)->create(['category_type' => 'accessory']); - // $accessory = factory(Accessory::class)->make(['category_id' => $category->id]); - // $accessory->save(); - // $this->assertTrue($accessory->isValid()); - // $newId = $category->id + 1; - // $accessory = factory(Accessory::class)->make(['category_id' => $newId]); - // $accessory->save(); + public function testAnAccessoryHasALocation() + { + $accessory = factory(Accessory::class) + ->create(['location_id' => factory(App\Models\Location::class)->create()->id]); + $this->assertInstanceOf(App\Models\Location::class, $accessory->location); + } - // $this->assertFalse($accessory->isValid()); - // } + public function testAnAccessoryBelongsToACategory() + { + $accessory = factory(Accessory::class)->states('apple-bt-keyboard') + ->create(['category_id' => factory(Category::class)->states('accessory-keyboard-category')->create(['category_type' => 'accessory'])->id]); + $this->assertInstanceOf(App\Models\Category::class, $accessory->category); + $this->assertEquals('accessory', $accessory->category->category_type); + } - // public function testAnAccessoryBelongsToACompany() - // { - // $accessory = factory(Accessory::class)->create(); - // $this->assertInstanceOf(App\Models\Company::class, $accessory->company); - // } - - // public function testAnAccessoryHasALocation() - // { - // $accessory = factory(Accessory::class)->create(); - // $this->assertInstanceOf(App\Models\Location::class, $accessory->location); - // } - - // public function testAnAccessoryBelongsToACategory() - // { - // $accessory = factory(Accessory::class)->create(); - // $this->assertInstanceOf(App\Models\Category::class, $accessory->category); - // $this->assertEquals('accessory', $accessory->category->category_type); - // } - - // public function testAnAccessoryHasAManufacturer() - // { - // $accessory = factory(Accessory::class)->create(); - // $this->assertInstanceOf(App\Models\Manufacturer::class, $accessory->manufacturer); - // } + public function testAnAccessoryHasAManufacturer() + { + $this->createValidManufacturer('apple'); + $this->createValidCategory('accessory-keyboard-category'); + $accessory = factory(Accessory::class)->states('apple-bt-keyboard')->create(['category_id' => 1]); + $this->assertInstanceOf(App\Models\Manufacturer::class, $accessory->manufacturer); + } } diff --git a/tests/unit/AssetModelTest.php b/tests/unit/AssetModelTest.php index d82061b6a..edb24243e 100644 --- a/tests/unit/AssetModelTest.php +++ b/tests/unit/AssetModelTest.php @@ -13,69 +13,58 @@ class AssetModelTest extends BaseTest */ protected $tester; - // public function testAssetModelAdd() - // { - // $assetmodel = factory(AssetModel::class)->make(); - // $values = [ - // 'name' => $assetmodel->name, - // 'manufacturer_id' => $assetmodel->manufacturer_id, - // 'category_id' => $assetmodel->category_id, - // 'eol' => $assetmodel->eol, - // ]; - // AssetModel::create($values); - // $this->tester->seeRecord('models', $values); - // } + public function testAnAssetModelRequiresAttributes() + { + // An Asset Model requires a name, a category_id, and a manufacturer_id. + $a = AssetModel::create(); + $this->assertFalse($a->isValid()); + $fields = [ + 'name' => 'name', + 'manufacturer_id' => 'manufacturer id', + 'category_id' => 'category id' + ]; + $errors = $a->getErrors(); + foreach ($fields as $field => $fieldTitle) { + $this->assertEquals($errors->get($field)[0], "The ${fieldTitle} field is required."); + } + } - // public function testAnAssetModelRequiresAttributes() - // { - // // An Asset Model requires a name, a category_id, and a manufacturer_id. - // $a = AssetModel::create(); - // $this->assertFalse($a->isValid()); - // $fields = [ - // 'name' => 'name', - // 'manufacturer_id' => 'manufacturer id', - // 'category_id' => 'category id' - // ]; - // $errors = $a->getErrors(); - // foreach ($fields as $field => $fieldTitle) { - // $this->assertEquals($errors->get($field)[0], "The ${fieldTitle} field is required."); - // } - // } + public function testAnAssetModelZerosOutBlankEols() + { + $am = new AssetModel; + $am->eol = ''; + $this->assertTrue($am->eol === 0); + $am->eol = '4'; + $this->assertTrue($am->eol==4); + } - // public function testAnAssetModelZerosOutBlankEols() - // { - // $am = new AssetModel; - // $am->eol = ''; - // $this->assertTrue($am->eol === 0); - // $am->eol = '4'; - // $this->assertTrue($am->eol==4); - // } + public function testAnAssetModelContainsAssets() + { + $assetModel = $this->createValidAssetModel(); + factory(Asset::class)->create([ + 'model_id' => $assetModel->id, + ]); + $this->assertEquals(1,$assetModel->assets()->count()); + } - // public function testAnAssetModelContainsAssets() - // { - // $assetmodel = factory(AssetModel::class)->create(); - // $asset = factory(Asset::class)->create([ - // 'model_id' => $assetmodel->id, - // ]); - // $this->assertEquals(1,$assetmodel->assets()->count()); - // } + public function testAnAssetModelHasACategory() + { + $assetmodel = $this->createValidAssetModel(); + $this->assertInstanceOf(App\Models\Category::class, $assetmodel->category); + } - // public function testAnAssetModelHasACategory() - // { - // $assetmodel = factory(AssetModel::class)->create(); - // $this->assertInstanceOf(App\Models\Category::class, $assetmodel->category); - // } + public function testAnAssetModelHasADepreciation() + { - // public function anAssetModelHasADepreciation() - // { - // $assetmodel = factory(AssetModel::class)->create(); - // $this->assertInstanceOf(App\Models\Depreciation::class, $assetmodel->depreciation); - // } + $assetmodel = $this->createValidAssetModel(); + $this->assertInstanceOf(App\Models\Depreciation::class, $assetmodel->depreciation); + } + + public function testAnAssetModelHasAManufacturer() + { + $assetmodel = $this->createValidAssetModel(); + $this->assertInstanceOf(App\Models\Manufacturer::class, $assetmodel->manufacturer); + } - // public function testAnAssetModelHasAManufacturer() - // { - // $assetmodel = factory(AssetModel::class)->create(); - // $this->assertInstanceOf(App\Models\Manufacturer::class, $assetmodel->manufacturer); - // } } diff --git a/tests/unit/AssetTest.php b/tests/unit/AssetTest.php index 1862f7032..7f93f53b1 100644 --- a/tests/unit/AssetTest.php +++ b/tests/unit/AssetTest.php @@ -5,6 +5,7 @@ use App\Models\AssetModel; use App\Models\Company; use App\Models\Location; use App\Models\User; +use Carbon\Carbon; use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Foundation\Testing\WithoutMiddleware; use Illuminate\Support\Facades\Hash; @@ -16,36 +17,23 @@ class AssetTest extends BaseTest */ protected $tester; - // public function testAssetAdd() - // { - // $asset = factory(Asset::class)->make(); - // $values = [ - // 'name' => $asset->name, - // 'model_id' => $asset->model_id, - // 'status_id' => $asset->status_id, - // 'asset_tag' => $asset->asset_tag, - // ]; - // Asset::create($values); - // $this->tester->seeRecord('assets', $values); - // } + public function testFailsEmptyValidation() + { + // An Asset requires a name, a qty, and a category_id. + $a = Asset::create(); + $this->assertFalse($a->isValid()); - // public function testFailsEmptyValidation() - // { - // // An Asset requires a name, a qty, and a category_id. - // $a = Asset::create(); - // $this->assertFalse($a->isValid()); - - // $fields = [ - // 'model_id' => 'model id', - // 'status_id' => 'status id', - // 'asset_tag' => 'asset tag' - // ]; - // $errors = $a->getErrors(); - // foreach ($fields as $field => $fieldTitle) { - // $this->assertEquals($errors->get($field)[0], "The ${fieldTitle} field is required."); - // } - // } + $fields = [ + 'model_id' => 'model id', + 'status_id' => 'status id', + 'asset_tag' => 'asset tag' + ]; + $errors = $a->getErrors(); + foreach ($fields as $field => $fieldTitle) { + $this->assertEquals($errors->get($field)[0], "The ${fieldTitle} field is required."); + } + } public function testAutoIncrementMixed() @@ -66,246 +54,258 @@ class AssetTest extends BaseTest $this->assertEquals($expected, $next); } -// public function testAutoIncrementMixedFullTagNumber() -// { -// $expected = '123411'; -// $next = Asset::nextAutoIncrement( -// [ -// ['asset_tag' => '0012345'], -// ['asset_tag' => 'WTF00134'], -// ['asset_tag' => 'WTF-745'], -// ['asset_tag' => '0012346'], -// ['asset_tag' => '00123410'], -// ['asset_tag' => 'U8T7597h77'] -// ] -// ); -// $this->assertEquals($expected, $next); -// } -// + public function testAutoIncrementMixedFullTagNumber() + { + $expected = '123411'; + $next = Asset::nextAutoIncrement( + [ + ['asset_tag' => '0012345'], + ['asset_tag' => 'WTF00134'], + ['asset_tag' => 'WTF-745'], + ['asset_tag' => '0012346'], + ['asset_tag' => '00123410'], + ['asset_tag' => 'U8T7597h77'] + ] + ); + $this->assertEquals($expected, $next); + } + /** * @test */ -// public function testWarrantyExpiresAttribute() -// { -// $asset = factory(\App\Models\Asset::class)->create(); + public function testWarrantyExpiresAttribute() + { + $asset = factory(Asset::class)->states('laptop-mbp')->create(['model_id' => $this->createValidAssetModel()->id]); -// $asset->purchase_date = \Carbon\Carbon::createFromDate(2017, 1, 1)->hour(0)->minute(0)->second(0); -// $asset->warranty_months = 24; -// $asset->save(); + $asset->purchase_date = Carbon::createFromDate(2017, 1, 1)->hour(0)->minute(0)->second(0); + $asset->warranty_months = 24; + $asset->save(); -// $saved_asset = \App\Models\Asset::find($asset->id); + $saved_asset = Asset::find($asset->id); -// $this->tester->assertInstanceOf(\DateTime::class, $saved_asset->purchase_date); -// $this->tester->assertEquals( -// \Carbon\Carbon::createFromDate(2017, 1, 1)->format('Y-m-d'), -// $saved_asset->purchase_date->format('Y-m-d') -// ); -// $this->tester->assertEquals( -// \Carbon\Carbon::createFromDate(2017, 1, 1)->setTime(0, 0, 0), -// $saved_asset->purchase_date -// ); -// $this->tester->assertEquals(24, $saved_asset->warranty_months); -// $this->tester->assertInstanceOf(\DateTime::class, $saved_asset->warranty_expires); -// $this->tester->assertEquals( -// \Carbon\Carbon::createFromDate(2019, 1, 1)->format('Y-m-d'), -// $saved_asset->warranty_expires->format('Y-m-d') -// ); -// $this->tester->assertEquals( -// \Carbon\Carbon::createFromDate(2019, 1, 1)->setTime(0, 0, 0), -// $saved_asset->warranty_expires -// ); -// } + $this->tester->assertInstanceOf(\DateTime::class, $saved_asset->purchase_date); + $this->tester->assertEquals( + Carbon::createFromDate(2017, 1, 1)->format('Y-m-d'), + $saved_asset->purchase_date->format('Y-m-d') + ); + $this->tester->assertEquals( + Carbon::createFromDate(2017, 1, 1)->setTime(0, 0, 0), + $saved_asset->purchase_date + ); + $this->tester->assertEquals(24, $saved_asset->warranty_months); + $this->tester->assertInstanceOf(\DateTime::class, $saved_asset->warranty_expires); + $this->tester->assertEquals( + Carbon::createFromDate(2019, 1, 1)->format('Y-m-d'), + $saved_asset->warranty_expires->format('Y-m-d') + ); + $this->tester->assertEquals( + Carbon::createFromDate(2019, 1, 1)->setTime(0, 0, 0), + $saved_asset->warranty_expires + ); + } -// public function testModelIdMustExist() -// { -// $model = factory(AssetModel::class)->create(); -// $asset = factory(Asset::class)->make(['model_id' => $model->id]); -// $asset->save(); -// $this->assertTrue($asset->isValid()); -// $newId = $model->id + 1; -// $asset = factory(Asset::class)->make(['model_id' => $newId]); -// $asset->save(); + public function testModelIdMustExist() + { + $model = $this->createValidAssetModel(); + $asset = factory(Asset::class)->make(['model_id' => $model->id]); + $asset->save(); + $this->assertTrue($asset->isValid()); + $newId = $model->id + 1; + $asset = factory(Asset::class)->make(['model_id' => $newId]); + $asset->save(); -// $this->assertFalse($asset->isValid()); -// } + $this->assertFalse($asset->isValid()); + } -// public function testAnAssetHasRelationships() -// { -// $asset = factory(Asset::class)->create(); -// $this->assertInstanceOf(AssetModel::class, $asset->model); -// $this->assertInstanceOf(Company::class, $asset->company); -// $this->assertInstanceOf(App\Models\Depreciation::class, $asset->depreciation); -// $this->assertInstanceOf(App\Models\Statuslabel::class, $asset->assetstatus); -// $this->assertInstanceOf(App\Models\Supplier::class, $asset->supplier); -// } + public function testAnAssetHasRelationships() + { + $asset = factory(Asset::class)->states('laptop-mbp') + ->create([ + 'model_id' => $this->createValidAssetModel()->id, + 'company_id' => $this->createValidCompany()->id, + 'supplier_id' => $this->createValidSupplier()->id, + ]); + $this->assertInstanceOf(AssetModel::class, $asset->model); + $this->assertInstanceOf(Company::class, $asset->company); + $this->assertInstanceOf(App\Models\Depreciation::class, $asset->depreciation); + $this->assertInstanceOf(App\Models\Statuslabel::class, $asset->assetstatus); + $this->assertInstanceOf(App\Models\Supplier::class, $asset->supplier); + } -// public function testAnAssetCanBeAvailableForCheckout() -// { -// // Logic: If the asset is not assigned to anyone, -// // and the statuslabel type is "deployable" -// // and the asset is not deleted -// // Then it is available for checkout + public function testAnAssetCanBeAvailableForCheckout() + { + // Logic: If the asset is not assigned to anyone, + // and the statuslabel type is "deployable" + // and the asset is not deleted + // Then it is available for checkout -// // An asset assigned to someone should not be available for checkout. -// $user = factory(App\Models\User::class)->create(); -// $assetAssigned = factory(Asset::class)->create(['assigned_to' => $user->id]); -// $this->assertFalse($assetAssigned->availableForCheckout()); + // An asset assigned to someone should not be available for checkout. + $assetAssigned = factory(Asset::class) + ->states('laptop-mbp', 'assigned-to-user') + ->create(['model_id' => $this->createValidAssetModel()]); + $this->assertFalse($assetAssigned->availableForCheckout()); -// // An asset with a non deployable statuslabel should not be available for checkout. -// $status = factory(App\Models\Statuslabel::class)->states('archived')->create(); -// $assetUndeployable = factory(Asset::class)->create(['status_id' => $status->id]); -// $this->assertFalse($assetUndeployable->availableForCheckout()); + // An asset with a non deployable statuslabel should not be available for checkout. + $assetUndeployable = factory(Asset::class)->create([ + 'status_id' => $this->createValidStatuslabel('archived')->id, + 'model_id' => $this->createValidAssetModel() + ]); -// // An asset that has been deleted is not avaiable for checkout. -// $assetDeleted = factory(Asset::class)->states('deleted')->create(); -// $this->assertFalse($assetDeleted->availableForCheckout()); + $this->assertFalse($assetUndeployable->availableForCheckout()); -// // A ready to deploy asset that isn't assigned to anyone is available for checkout -// $status = factory(App\Models\Statuslabel::class)->states('rtd')->create(); -// $asset = factory(Asset::class)->create(['status_id' => $status->id]); -// $this->assertTrue($asset->availableForCheckout()); -// } + // An asset that has been deleted is not avaiable for checkout. + $assetDeleted = factory(Asset::class)->states('deleted')->create([ + 'model_id' => $this->createValidAssetModel() + ]); + $this->assertFalse($assetDeleted->availableForCheckout()); -// public function testAnAssetCanHaveComponents() -// { -// $asset = factory(Asset::class)->create(); -// $components = factory(App\Models\Component::class, 5)->create(); -// $components->each(function($component) use ($asset) { -// $component->assets()->attach($component, [ -// 'asset_id'=>$asset->id -// ]); -// }); -// $this->assertInstanceOf(App\Models\Component::class, $asset->components()->first()); -// $this->assertCount(5, $asset->components); -// } + // A ready to deploy asset that isn't assigned to anyone is available for checkout + $asset = factory(Asset::class)->create([ + 'status_id' => $this->createValidStatuslabel('rtd')->id, + 'model_id' => $this->createValidAssetModel() + ]); + $this->assertTrue($asset->availableForCheckout()); + } -// public function testAnAssetCanHaveUploads() -// { -// $asset = factory(Asset::class)->create(); -// $this->assertCount(0, $asset->uploads); -// factory(App\Models\Actionlog::class, 'asset-upload')->create(['item_id' => $asset->id]); -// $this->assertCount(1, $asset->fresh()->uploads); -// } + public function testAnAssetCanHaveComponents() + { + $asset = $this->createValidAsset(); -// // Helper Method for checking in assets.... We should extract this to the model or a trait. + $components = factory(App\Models\Component::class, 5)->states('ram-crucial4')->create([ + 'category_id' => $this->createValidCategory('component-hdd-category')->id + ]); -// private function checkin($asset, $target) { -// $asset->expected_checkin = null; -// $asset->last_checkout = null; -// $asset->assigned_to = null; -// $asset->assigned_type = null; -// $asset->assignedTo()->disassociate($asset); -// $asset->accepted = null; -// $asset->save(); -// $asset->logCheckin($target, 'Test Checkin'); -// } + $components->each(function($component) use ($asset) { + $component->assets()->attach($component, [ + 'asset_id'=>$asset->id + ]); + }); + $this->assertInstanceOf(App\Models\Component::class, $asset->components()->first()); + $this->assertCount(5, $asset->components); + } -// public function testAnAssetCanBeCheckedOut() -// { -// // This tests Asset::checkOut(), Asset::assignedTo(), Asset::assignedAssets(), Asset::assetLoc(), Asset::assignedType(), defaultLoc() -// $asset = factory(Asset::class)->create(); -// $adminUser = $this->signIn(); + public function testAnAssetCanHaveUploads() + { + $asset = $this->createValidAsset(); + $this->assertCount(0, $asset->uploads); + factory(App\Models\Actionlog::class, 'asset-upload')->create(['item_id' => $asset->id]); + $this->assertCount(1, $asset->fresh()->uploads); + } -// $target = factory(App\Models\User::class)->create(); -// // An Asset Can be checked out to a user, and this should be logged. -// $asset->checkOut($target, $adminUser); -// $asset->save(); + // Helper Method for checking in assets.... We should extract this to the model or a trait. -// $this->assertInstanceOf(App\Models\User::class, $asset->assignedTo); -// $this->assertEquals($asset->assetLoc->id, $target->userLoc->id); -// $this->assertEquals('user', $asset->assignedType()); -// $this->assertEquals($asset->defaultLoc->id, $asset->rtd_location_id); -// $this->tester->seeRecord('action_logs', [ -// 'action_type' => 'checkout', -// 'target_type' => get_class($target), -// 'target_id' => $target->id -// ]); + private function checkin($asset, $target) { + $asset->expected_checkin = null; + $asset->last_checkout = null; + $asset->assigned_to = null; + $asset->assigned_type = null; + $asset->location_id = $asset->rtd_location_id; + $asset->assignedTo()->disassociate($asset); + $asset->accepted = null; + $asset->save(); + $asset->logCheckin($target, 'Test Checkin'); + } -// $this->tester->seeRecord('assets', [ -// 'id' => $asset->id, -// 'assigned_to' => $target->id, -// 'assigned_type' => User::class -// ]); + public function testAnAssetCanBeCheckedOut() + { + // This tests Asset::checkOut(), Asset::assignedTo(), Asset::assignedAssets(), Asset::assetLoc(), Asset::assignedType(), defaultLoc() + $asset = $this->createValidAsset(); + $adminUser = $this->signIn(); -// $this->checkin($asset, $target); -// $this->assertNull($asset->fresh()->assignedTo); + $target = factory(App\Models\User::class)->create([ + 'location_id' => factory(App\Models\Location::class)->create() + ]); + // An Asset Can be checked out to a user, and this should be logged. + $asset->checkOut($target, $adminUser); + $asset->save(); + $this->assertInstanceOf(App\Models\User::class, $asset->assignedTo); -// $this->tester->seeRecord('action_logs', [ -// 'action_type' => 'checkin from', -// 'target_type' => get_class($target), -// 'target_id' => $target->id -// ]); + $this->assertEquals($asset->location->id, $target->userLoc->id); + $this->assertEquals('user', $asset->assignedType()); + $this->assertEquals($asset->defaultLoc->id, $asset->rtd_location_id); + $this->tester->seeRecord('action_logs', [ + 'action_type' => 'checkout', + 'target_type' => get_class($target), + 'target_id' => $target->id + ]); -// $this->tester->seeRecord('assets', [ -// 'id' => $asset->id, -// 'assigned_to' => null, -// 'assigned_type' => null -// ]); + $this->tester->seeRecord('assets', [ + 'id' => $asset->id, + 'assigned_to' => $target->id, + 'assigned_type' => User::class + ]); -// // An Asset Can be checked out to a asset, and this should be logged. -// $target = factory(App\Models\Asset::class)->create(); -// $asset->checkOut($target, $adminUser); -// $asset->save(); -// $this->assertInstanceOf(App\Models\Asset::class, $asset->fresh()->assignedTo); -// $this->assertEquals($asset->fresh()->assetLoc->id, $target->fresh()->assetLoc->id); -// $this->assertEquals('asset', $asset->assignedType()); -// $this->assertEquals($asset->defaultLoc->id, $asset->rtd_location_id); -// $this->tester->seeRecord('action_logs', [ -// 'action_type' => 'checkout', -// 'target_type' => get_class($target), -// 'target_id' => $target->id -// ]); + $this->checkin($asset, $target); + $this->assertNull($asset->fresh()->assignedTo); -// $this->assertCount(1, $target->assignedAssets); -// $this->checkin($asset, $target); -// $this->assertNull($asset->fresh()->assignedTo); + $this->tester->seeRecord('action_logs', [ + 'action_type' => 'checkin from', + 'target_type' => get_class($target), + 'target_id' => $target->id + ]); -// $this->tester->seeRecord('action_logs', [ -// 'action_type' => 'checkin from', -// 'target_type' => get_class($target), -// 'target_id' => $target->id -// ]); + $this->tester->seeRecord('assets', [ + 'id' => $asset->id, + 'assigned_to' => null, + 'assigned_type' => null + ]); -// // An Asset Can be checked out to a location, and this should be logged. -// $target = factory(App\Models\Location::class)->create(); -// $asset->checkOut($target, $adminUser); -// $asset->save(); -// $this->assertInstanceOf(App\Models\Location::class, $asset->fresh()->assignedTo); -// $this->assertEquals($asset->fresh()->assetLoc->id, $target->fresh()->id); -// $this->assertEquals('location', $asset->assignedType()); -// $this->assertEquals($asset->defaultLoc->id, $asset->rtd_location_id); -// $this->tester->seeRecord('action_logs', [ -// 'action_type' => 'checkout', -// 'target_type' => get_class($target), -// 'target_id' => $target->id -// ]); -// $this->checkin($asset, $target); -// $this->assertNull($asset->fresh()->assignedTo); + // An Asset Can be checked out to a asset, and this should be logged. + $target = $this->createValidAsset(); -// $this->tester->seeRecord('action_logs', [ -// 'action_type' => 'checkin from', -// 'target_type' => get_class($target), -// 'target_id' => $target->id -// ]); -// } + $asset->checkOut($target, $adminUser); + $asset->save(); + $this->assertInstanceOf(App\Models\Asset::class, $asset->fresh()->assignedTo); + $this->assertEquals($asset->fresh()->location->id, $target->fresh()->location->id); + $this->assertEquals('asset', $asset->assignedType()); + $this->assertEquals($asset->defaultLoc->id, $asset->rtd_location_id); + $this->tester->seeRecord('action_logs', [ + 'action_type' => 'checkout', + 'target_type' => get_class($target), + 'target_id' => $target->id + ]); -// public function testAnAssetHasMaintenances() -// { -// $asset = factory(Asset::class)->create(); -// factory(App\Models\AssetMaintenance::class)->create(['asset_id' => $asset->id]); -// $this->assertCount(1, $asset->assetmaintenances); -// } + $this->assertCount(1, $target->assignedAssets); + $this->checkin($asset, $target); + $this->assertNull($asset->fresh()->assignedTo); -// public function testAnAssetThatRequiresAcceptanceCanNotBeCheckedOutToANonUser() -// { -// $this->expectException(CheckoutNotAllowed::class); -// $this->signIn(); + $this->tester->seeRecord('action_logs', [ + 'action_type' => 'checkin from', + 'target_type' => get_class($target), + 'target_id' => $target->id + ]); -// $asset = factory(Asset::class)->states('requires-acceptance')->create(); + // An Asset Can be checked out to a location, and this should be logged. + $target = $this->createValidLocation(); -// $location = factory(Location::class)->create(); -// $asset->checkOut($location); -// } + $asset->checkOut($target, $adminUser); + $asset->save(); + $this->assertInstanceOf(App\Models\Location::class, $asset->fresh()->assignedTo); + + $this->assertEquals($asset->fresh()->location->id, $target->fresh()->id); + $this->assertEquals('location', $asset->assignedType()); + $this->assertEquals($asset->defaultLoc->id, $asset->rtd_location_id); + $this->tester->seeRecord('action_logs', [ + 'action_type' => 'checkout', + 'target_type' => get_class($target), + 'target_id' => $target->id + ]); + $this->checkin($asset, $target); + $this->assertNull($asset->fresh()->assignedTo); + + $this->tester->seeRecord('action_logs', [ + 'action_type' => 'checkin from', + 'target_type' => get_class($target), + 'target_id' => $target->id + ]); + } + + public function testAnAssetHasMaintenances() + { + $asset = $this->createValidAsset(); + factory(App\Models\AssetMaintenance::class)->create(['asset_id' => $asset->id]); + $this->assertCount(1, $asset->assetmaintenances); + } } diff --git a/tests/unit/BaseTest.php b/tests/unit/BaseTest.php index d862e4117..9b77c802b 100644 --- a/tests/unit/BaseTest.php +++ b/tests/unit/BaseTest.php @@ -22,4 +22,74 @@ class BaseTest extends \Codeception\TestCase\Test return $user; } + + + protected function createValidAssetModel($state = 'mbp-13-model', $overrides = []) + { + return factory(\App\Models\AssetModel::class)->states($state)->create(array_merge([ + 'category_id' => $this->createValidCategory(), + 'manufacturer_id' => $this->createValidManufacturer(), + 'depreciation_id' => $this->createValidDepreciation(), + ],$overrides)); + } + + protected function createValidCategory($state = 'asset-laptop-category', $overrides = []) + { + return factory(App\Models\Category::class)->states($state)->create($overrides); + } + + protected function createValidCompany($overrides = []) + { + return factory(App\Models\Company::class)->create($overrides); + } + + + protected function createValidDepartment($state = 'engineering', $overrides = []) + { + return factory(App\Models\Department::class)->states($state)->create(array_merge([ + 'location_id' => $this->createValidLocation()->id + ], $overrides)); + } + + protected function createValidDepreciation($state = 'computer', $overrides = []) + { + return factory(App\Models\Depreciation::class)->states($state)->create($overrides); + } + + protected function createValidLocation($overrides = []) + { + return factory(App\Models\Location::class)->create($overrides); + } + + protected function createValidManufacturer($state = 'apple', $overrides = []) + { + return factory(App\Models\Manufacturer::class)->states($state)->create($overrides); + } + + protected function createValidSupplier($overrides = []) + { + return factory(App\Models\Supplier::class)->create($overrides); + } + + protected function createValidStatuslabel($state = 'rtd', $overrides= []) + { + return factory(App\Models\Statuslabel::class)->states($state)->create($overrides); + } + + protected function createValidUser($overrides= []) + { + return factory(App\Models\User::class)->create($overrides); + } + + protected function createValidAsset($overrides = []) + { + $locId = $this->createValidLocation(); + $this->createValidAssetModel(); + return factory(\App\Models\Asset::class)->states('laptop-mbp')->create([ + 'rtd_location_id' => $locId, + 'location_id' => $locId + ], $overrides); + } + + } diff --git a/tests/unit/CategoryTest.php b/tests/unit/CategoryTest.php index 3edf78505..3fa114bb5 100644 --- a/tests/unit/CategoryTest.php +++ b/tests/unit/CategoryTest.php @@ -12,84 +12,59 @@ class CategoryTest extends BaseTest */ protected $tester; -// public function testAssetCategoryAdd() -// { -// $category = factory(Category::class)->make(['category_type' => 'asset']); -// $values = [ -// 'name' => $category->name, -// 'category_type' => $category->category_type, -// 'require_acceptance' => true, -// 'use_default_eula' => false -// ]; + public function testFailsEmptyValidation() + { + // An Asset requires a name, a qty, and a category_id. + $a = Category::create(); + $this->assertFalse($a->isValid()); -// Category::create($values); -// $this->tester->seeRecord('categories', $values); -// } + $fields = [ + 'name' => 'name', + 'category_type' => 'category type' + ]; + $errors = $a->getErrors(); + foreach ($fields as $field => $fieldTitle) { + $this->assertEquals($errors->get($field)[0], "The ${fieldTitle} field is required."); + } + } -// public function testAccessoryCategoryAdd() -// { -// $category = factory(Category::class)->make(['category_type' => 'accessory']); -// $values = [ -// 'name' => $category->name, -// 'category_type' => $category->category_type, -// 'require_acceptance' => true, -// 'use_default_eula' => false -// ]; + public function testACategoryCanHaveAssets() + { + $this->createValidAssetModel(); //This will seed various things to make the following work better. + $category = $this->createValidCategory('asset-desktop-category'); + $models = factory(App\Models\AssetModel::class, 5)->states('mbp-13-model')->create(['category_id' => $category->id]); -// Category::create($values); -// $this->tester->seeRecord('categories', $values); -// } + $this->assertEquals(5, $category->has_models()); + $this->assertCount(5, $category->models); -// public function testFailsEmptyValidation() -// { -// // An Asset requires a name, a qty, and a category_id. -// $a = Category::create(); -// $this->assertFalse($a->isValid()); + $models->each(function($model) { + factory(App\Models\Asset::class, 2)->create(['model_id' => $model->id]); + }); + $this->assertEquals(10, $category->itemCount()); + } -// $fields = [ -// 'name' => 'name', -// 'category_type' => 'category type' -// ]; -// $errors = $a->getErrors(); -// foreach ($fields as $field => $fieldTitle) { -// $this->assertEquals($errors->get($field)[0], "The ${fieldTitle} field is required."); -// } -// } + public function testACategoryCanHaveAccessories() + { + $category = $this->createValidCategory('accessory-keyboard-category'); + factory(App\Models\Accessory::class, 5)->states('apple-bt-keyboard')->create(['category_id' => $category->id]); -// public function testACategoryCanHaveAssets() -// { -// $category = factory(Category::class)->create(['category_type' => 'asset']); -// $models = factory(App\Models\AssetModel::class, 5)->create(['category_id' => $category->id]); -// $this->assertEquals(5, $category->has_models()); -// $this->assertCount(5, $category->models); + $this->assertCount(5, $category->accessories); + $this->assertEquals(5, $category->itemCount()); + } -// $models->each(function($model) { -// factory(App\Models\Asset::class, 2)->create(['model_id' => $model->id]); -// }); -// $this->assertEquals(10, $category->itemCount()); -// } + public function testACategoryCanHaveConsumables() + { + $category = $this->createValidCategory('consumable-paper-category'); + factory(App\Models\Consumable::class, 5)->states('cardstock')->create(['category_id' => $category->id]); + $this->assertCount(5, $category->consumables); + $this->assertEquals(5, $category->itemCount()); + } -// public function testACategoryCanHaveAccessories() -// { -// $category = factory(Category::class)->create(['category_type' => 'accessory']); -// factory(App\Models\Accessory::class, 5)->create(['category_id' => $category->id]); -// $this->assertCount(5, $category->accessories); -// $this->assertEquals(5, $category->itemCount()); -// } - -// public function testACategoryCanHaveConsumables() -// { -// $category = factory(Category::class)->create(['category_type' => 'consumable']); -// factory(App\Models\Consumable::class, 5)->create(['category_id' => $category->id]); -// $this->assertCount(5, $category->consumables); -// $this->assertEquals(5, $category->itemCount()); -// } - -// public function testACategoryCanHaveComponents() -// { -// $category = factory(Category::class)->create(['category_type' => 'component']); -// factory(App\Models\Component::class, 5)->create(['category_id' => $category->id]); -// $this->assertCount(5, $category->components); -// $this->assertEquals(5, $category->itemCount()); -// } + public function testACategoryCanHaveComponents() + { + $category = $this->createValidCategory('component-ram-category'); + factory(App\Models\Component::class, 5)->states('ram-crucial4')->create(['category_id' => $category->id]); + $this->assertCount(5, $category->components); + $this->assertEquals(5, $category->itemCount()); + } } diff --git a/tests/unit/CompanyTest.php b/tests/unit/CompanyTest.php index 9d90a960f..59930ba4c 100644 --- a/tests/unit/CompanyTest.php +++ b/tests/unit/CompanyTest.php @@ -12,71 +12,78 @@ class CompanyTest extends BaseTest */ protected $tester; - // public function testCompanyAdd() - // { - // $company = factory(Company::class)->make(); - // $values = [ - // 'name' => $company->name, - // ]; - // Company::create($values); - // $this->tester->seeRecord('companies', $values); - // } + public function testFailsEmptyValidation() + { + // An Company requires a name, a qty, and a category_id. + $a = Company::create(); + $this->assertFalse($a->isValid()); - // public function testFailsEmptyValidation() - // { - // // An Company requires a name, a qty, and a category_id. - // $a = Company::create(); - // $this->assertFalse($a->isValid()); + $fields = [ + 'name' => 'name', + ]; + $errors = $a->getErrors(); + foreach ($fields as $field => $fieldTitle) { + $this->assertEquals($errors->get($field)[0], "The ${fieldTitle} field is required."); + } + } - // $fields = [ - // 'name' => 'name', - // ]; - // $errors = $a->getErrors(); - // foreach ($fields as $field => $fieldTitle) { - // $this->assertEquals($errors->get($field)[0], "The ${fieldTitle} field is required."); - // } - // } + public function testACompanyCanHaveUsers() + { + $company = $this->createValidCompany(); + factory(App\Models\User::class, 1)->create(['company_id'=>$company->id]); + $this->assertCount(1, $company->users); + } - // public function testACompanyCanHaveUsers() - // { - // $company = factory(Company::class)->create(); - // factory(App\Models\User::class, 1)->create(['company_id'=>$company->id]); - // $this->assertCount(1, $company->users); - // } + public function testACompanyCanHaveAssets() + { + $company = $this->createValidCompany(); + factory(App\Models\Asset::class, 1)->states('laptop-mbp')->create([ + 'company_id' => $company->id, + 'model_id' => $this->createValidAssetModel()->id + ]); + $this->assertCount(1, $company->assets); + } - // public function testACompanyCanHaveAssets() - // { - // $company = factory(Company::class)->create(); - // factory(App\Models\Asset::class, 1)->create(['company_id'=>$company->id]); - // $this->assertCount(1, $company->assets); - // } + public function testACompanyCanHaveLicenses() + { + $company = $this->createValidCompany(); + factory(App\Models\License::class, 1)->states('acrobat')->create([ + 'company_id'=>$company->id, + 'manufacturer_id' => factory(App\Models\Manufacturer::class)->states('adobe')->create()->id, + 'category_id' => factory(App\Models\Category::class)->states('license-office-category')->create()->id + ]); + $this->assertCount(1, $company->licenses); + } - // public function testACompanyCanHaveLicenses() - // { - // $company = factory(Company::class)->create(); - // factory(App\Models\License::class, 1)->create(['company_id'=>$company->id]); - // $this->assertCount(1, $company->licenses); - // } + public function testACompanyCanHaveAccessories() + { + $company = $this->createValidCompany(); + $a = factory(App\Models\Accessory::class)->states('apple-bt-keyboard')->create([ + 'category_id' => factory(App\Models\Category::class)->states('accessory-keyboard-category')->create()->id, + 'company_id' => $company->id + ]); - // public function testACompanyCanHaveAccessories() - // { - // $company = factory(Company::class)->create(); - // factory(App\Models\Accessory::class, 1)->create(['company_id'=>$company->id]); - // $this->assertCount(1, $company->accessories); - // } + $this->assertCount(1, $company->accessories); + } - // public function testACompanyCanHaveConsumables() - // { - // $company = factory(Company::class)->create(); - // factory(App\Models\Consumable::class, 1)->create(['company_id'=>$company->id]); - // $this->assertCount(1, $company->consumables); - // } + public function testACompanyCanHaveConsumables() + { + $company = $this->createValidCompany(); + factory(App\Models\Consumable::class, 1)->states('cardstock')->create([ + 'company_id' => $company->id, + 'category_id' => factory(App\Models\Category::class)->states('consumable-paper-category')->create()->id + ]); + $this->assertCount(1, $company->consumables); + } - // public function testACompanyCanHaveComponents() - // { - // $company = factory(Company::class)->create(); - // factory(App\Models\Component::class, 1)->create(['company_id'=>$company->id]); - // $this->assertCount(1, $company->components); - // } + public function testACompanyCanHaveComponents() + { + $company = $this->createValidCompany(); + factory(App\Models\Component::class, 1)->states('ram-crucial4')->create([ + 'company_id'=>$company->id, + 'category_id' => factory(App\Models\Category::class)->states('component-ram-category')->create()->id + ]); + $this->assertCount(1, $company->components); + } } diff --git a/tests/unit/ConsumableTest.php b/tests/unit/ConsumableTest.php index eca8cc760..1126594a1 100644 --- a/tests/unit/ConsumableTest.php +++ b/tests/unit/ConsumableTest.php @@ -12,45 +12,39 @@ class ConsumableTest extends BaseTest */ protected $tester; - // public function testConsumableAdd() - // { - // $consumable = factory(Consumable::class)->make(); - // $values = [ - // 'name' => $consumable->name, - // 'qty' => $consumable->qty, - // 'category_id' => $consumable->category_id, - // 'company_id' => $consumable->company_id, - // ]; - // Consumable::create($values); - // $this->tester->seeRecord('consumables', $values); - // } + public function testFailsEmptyValidation() + { + // An Consumable requires a name, a qty, and a category_id. + $a = Consumable::create(); + $this->assertFalse($a->isValid()); - // public function testFailsEmptyValidation() - // { - // // An Consumable requires a name, a qty, and a category_id. - // $a = Consumable::create(); - // $this->assertFalse($a->isValid()); + $fields = [ + 'name' => 'name', + 'qty' => 'qty', + 'category_id' => 'category id' + ]; + $errors = $a->getErrors(); + foreach ($fields as $field => $fieldTitle) { + $this->assertEquals($errors->get($field)[0], "The ${fieldTitle} field is required."); + } + } - // $fields = [ - // 'name' => 'name', - // 'qty' => 'qty', - // 'category_id' => 'category id' - // ]; - // $errors = $a->getErrors(); - // foreach ($fields as $field => $fieldTitle) { - // $this->assertEquals($errors->get($field)[0], "The ${fieldTitle} field is required."); - // } - // } - - // public function testAConsumableHasRelationships() - // { - // $consumable = factory(Consumable::class)->create(); - // $this->assertInstanceOf(App\Models\User::class, $consumable->admin); - // $this->assertInstanceOf(App\Models\Company::class, $consumable->company); - // $this->assertInstanceOf(App\Models\Manufacturer::class, $consumable->manufacturer); - // $this->assertInstanceOf(App\Models\Location::class, $consumable->location); - // $this->assertInstanceOf(App\Models\Category::class, $consumable->category); - // } + public function testAConsumableHasRelationships() + { + $consumable = factory(Consumable::class)->states('cardstock')->create([ + 'category_id' => $this->createValidCategory('consumable-paper-category')->id, + 'manufacturer_id' => $this->createValidManufacturer('apple')->id, + 'company_id' => $this->createValidCompany()->id, + 'location_id' => $this->createValidLocation()->id, + 'user_id' => $this->signIn()->id + ]); + + $this->assertInstanceOf(App\Models\User::class, $consumable->admin); + $this->assertInstanceOf(App\Models\Company::class, $consumable->company); + $this->assertInstanceOf(App\Models\Manufacturer::class, $consumable->manufacturer); + $this->assertInstanceOf(App\Models\Location::class, $consumable->location); + $this->assertInstanceOf(App\Models\Category::class, $consumable->category); + } } diff --git a/tests/unit/DepreciationTest.php b/tests/unit/DepreciationTest.php index 7bd20a1ad..b1c5416e1 100644 --- a/tests/unit/DepreciationTest.php +++ b/tests/unit/DepreciationTest.php @@ -11,45 +11,39 @@ class DepreciationTest extends BaseTest */ protected $tester; - // public function testDepreciationAdd() - // { - // $depreciations = factory(Depreciation::class)->make(); - // $values = [ - // 'name' => $depreciations->name, - // 'months' => $depreciations->months, - // ]; + public function testFailsEmptyValidation() + { + // An Asset requires a name, a qty, and a category_id. + $a = Depreciation::create(); + $this->assertFalse($a->isValid()); - // Depreciation::create($values); - // $this->tester->seeRecord('depreciations', $values); - // } + $fields = [ + 'name' => 'name', + 'months' => 'months', + ]; + $errors = $a->getErrors(); + foreach ($fields as $field => $fieldTitle) { + $this->assertEquals($errors->get($field)[0], "The ${fieldTitle} field is required."); + } + } - // public function testFailsEmptyValidation() - // { - // // An Asset requires a name, a qty, and a category_id. - // $a = Depreciation::create(); - // $this->assertFalse($a->isValid()); + public function testADepreciationHasModels() + { + $this->createValidAssetModel(); + $depreciation = $this->createValidDepreciation('computer', ['name' => 'New Depreciation']); + $models = factory(App\Models\AssetModel::class, 5)->states('mbp-13-model')->create(['depreciation_id'=>$depreciation->id]); + $this->assertEquals(5,$depreciation->has_models()); + } - // $fields = [ - // 'name' => 'name', - // 'months' => 'months', - // ]; - // $errors = $a->getErrors(); - // foreach ($fields as $field => $fieldTitle) { - // $this->assertEquals($errors->get($field)[0], "The ${fieldTitle} field is required."); - // } - // } + public function testADepreciationHasLicenses() + { + $category = $this->createValidCategory('license-graphics-category'); + $depreciation = $this->createValidDepreciation('computer', ['name' => 'New Depreciation']); + $licenses = factory(App\Models\License::class, 5)->states('photoshop')->create([ + 'depreciation_id'=>$depreciation->id, + 'category_id' => $category->id + ]); - // public function testADepreciationHasModels() - // { - // $depreciation = factory(Depreciation::class)->create(); - // factory(App\Models\AssetModel::class, 5)->create(['depreciation_id'=>$depreciation->id]); - // $this->assertEquals(5,$depreciation->has_models()); - // } - - // public function testADepreciationHasLicenses() - // { - // $depreciation = factory(Depreciation::class)->create(); - // factory(App\Models\License::class, 5)->create(['depreciation_id'=>$depreciation->id]); - // $this->assertEquals(5,$depreciation->has_licenses()); - // } + $this->assertEquals(5,$depreciation->has_licenses()); + } } diff --git a/tests/unit/NotificationTest.php b/tests/unit/NotificationTest.php index db7c1961a..10bbe7228 100644 --- a/tests/unit/NotificationTest.php +++ b/tests/unit/NotificationTest.php @@ -19,31 +19,17 @@ class NotificationTest extends BaseTest */ protected $tester; - // public function testAUserIsEmailedIfTheyCheckoutAnAssetWithEULA() - // { - // $admin = factory(User::class)->states('superuser')->create(); - // Auth::login($admin); - // $cat = factory(Category::class)->states('asset-category', 'requires-acceptance')->create(); - // $model = factory(AssetModel::class)->create(['category_id' => $cat->id]); - // $asset = factory(Asset::class)->create(['model_id' => $model->id]); + public function testAUserIsEmailedIfTheyCheckoutAnAssetWithEULA() + { + $admin = factory(User::class)->states('superuser')->create(); + Auth::login($admin); + $cat = $this->createValidCategory('asset-laptop-category', ['require_acceptance' => true]); + $model = $this->createValidAssetModel('mbp-13-model', ['category_id' => $cat->id]); + $asset = $this->createValidAsset(['model_id' => $model->id]); + $user = factory(User::class)->create(); + Notification::fake(); + $asset->checkOut($user, 1); - // $user = factory(User::class)->create(); - // Notification::fake(); - // $asset->checkOut($user, 1); - - // Notification::assertSentTo($user, CheckoutNotification::class); - // } - - // public function testAnAssetRequiringAEulaDoesNotExplodeWhenCheckedOutToALocation() - // { - // $this->signIn(); - // $asset = factory(Asset::class)->states('requires-acceptance')->create(); - - // $this->expectException(CheckoutNotAllowed::class); - // $location = factory(Location::class)->create(); - // Notification::fake(); - // $asset->checkOut($location, 1); - - // Notification::assertNotSentTo($location, CheckoutNotification::class); - // } + Notification::assertSentTo($user, CheckoutAssetNotification::class); + } } diff --git a/tests/unit/StatuslabelTest.php b/tests/unit/StatuslabelTest.php index 1dfa11041..8884537cc 100644 --- a/tests/unit/StatuslabelTest.php +++ b/tests/unit/StatuslabelTest.php @@ -12,102 +12,102 @@ class StatuslabelTest extends BaseTest */ protected $tester; - // public function testRTDStatuslabelAdd() - // { - // $statuslabel = factory(Statuslabel::class)->states('rtd')->make(); - // $values = [ - // 'name' => $statuslabel->name, - // 'deployable' => $statuslabel->deployable, - // 'pending' => $statuslabel->pending, - // 'archived' => $statuslabel->archived, + public function testRTDStatuslabelAdd() + { + $statuslabel = factory(Statuslabel::class)->states('rtd')->make(); + $values = [ + 'name' => $statuslabel->name, + 'deployable' => $statuslabel->deployable, + 'pending' => $statuslabel->pending, + 'archived' => $statuslabel->archived, - // ]; + ]; - // Statuslabel::create($values); - // $this->tester->seeRecord('status_labels', $values); - // } + Statuslabel::create($values); + $this->tester->seeRecord('status_labels', $values); + } - // public function testPendingStatuslabelAdd() - // { - // $statuslabel = factory(Statuslabel::class)->states('pending')->make(); - // $values = [ - // 'name' => $statuslabel->name, - // 'deployable' => $statuslabel->deployable, - // 'pending' => $statuslabel->pending, - // 'archived' => $statuslabel->archived, - // ]; + public function testPendingStatuslabelAdd() + { + $statuslabel = factory(Statuslabel::class)->states('pending')->make(); + $values = [ + 'name' => $statuslabel->name, + 'deployable' => $statuslabel->deployable, + 'pending' => $statuslabel->pending, + 'archived' => $statuslabel->archived, + ]; - // Statuslabel::create($values); - // $this->tester->seeRecord('status_labels', $values); - // } + Statuslabel::create($values); + $this->tester->seeRecord('status_labels', $values); + } - // public function testArchivedStatuslabelAdd() - // { - // $statuslabel = factory(Statuslabel::class)->states('archived')->make(); - // $values = [ - // 'name' => $statuslabel->name, - // 'deployable' => $statuslabel->deployable, - // 'pending' => $statuslabel->pending, - // 'archived' => $statuslabel->archived, - // ]; + public function testArchivedStatuslabelAdd() + { + $statuslabel = factory(Statuslabel::class)->states('archived')->make(); + $values = [ + 'name' => $statuslabel->name, + 'deployable' => $statuslabel->deployable, + 'pending' => $statuslabel->pending, + 'archived' => $statuslabel->archived, + ]; - // Statuslabel::create($values); - // $this->tester->seeRecord('status_labels', $values); - // } + Statuslabel::create($values); + $this->tester->seeRecord('status_labels', $values); + } - // public function testOutForRepairStatuslabelAdd() - // { - // $statuslabel = factory(Statuslabel::class)->states('out_for_repair')->make(); - // $values = [ - // 'name' => $statuslabel->name, - // 'deployable' => $statuslabel->deployable, - // 'pending' => $statuslabel->pending, - // 'archived' => $statuslabel->archived, - // ]; + public function testOutForRepairStatuslabelAdd() + { + $statuslabel = factory(Statuslabel::class)->states('out_for_repair')->make(); + $values = [ + 'name' => $statuslabel->name, + 'deployable' => $statuslabel->deployable, + 'pending' => $statuslabel->pending, + 'archived' => $statuslabel->archived, + ]; - // Statuslabel::create($values); - // $this->tester->seeRecord('status_labels', $values); - // } + Statuslabel::create($values); + $this->tester->seeRecord('status_labels', $values); + } - // public function testOutForDiagnosticsStatuslabelAdd() - // { - // $statuslabel = factory(Statuslabel::class)->states('out_for_diagnostics')->make(); - // $values = [ - // 'name' => $statuslabel->name, - // 'deployable' => $statuslabel->deployable, - // 'pending' => $statuslabel->pending, - // 'archived' => $statuslabel->archived, - // ]; + public function testOutForDiagnosticsStatuslabelAdd() + { + $statuslabel = factory(Statuslabel::class)->states('out_for_diagnostics')->make(); + $values = [ + 'name' => $statuslabel->name, + 'deployable' => $statuslabel->deployable, + 'pending' => $statuslabel->pending, + 'archived' => $statuslabel->archived, + ]; - // Statuslabel::create($values); - // $this->tester->seeRecord('status_labels', $values); - // } + Statuslabel::create($values); + $this->tester->seeRecord('status_labels', $values); + } - // public function testBrokenStatuslabelAdd() - // { - // $statuslabel = factory(Statuslabel::class)->states('broken')->make(); - // $values = [ - // 'name' => $statuslabel->name, - // 'deployable' => $statuslabel->deployable, - // 'pending' => $statuslabel->pending, - // 'archived' => $statuslabel->archived, - // ]; + public function testBrokenStatuslabelAdd() + { + $statuslabel = factory(Statuslabel::class)->states('broken')->make(); + $values = [ + 'name' => $statuslabel->name, + 'deployable' => $statuslabel->deployable, + 'pending' => $statuslabel->pending, + 'archived' => $statuslabel->archived, + ]; - // Statuslabel::create($values); - // $this->tester->seeRecord('status_labels', $values); - // } + Statuslabel::create($values); + $this->tester->seeRecord('status_labels', $values); + } - // public function testLostStatuslabelAdd() - // { - // $statuslabel = factory(Statuslabel::class)->states('lost')->make(); - // $values = [ - // 'name' => $statuslabel->name, - // 'deployable' => $statuslabel->deployable, - // 'pending' => $statuslabel->pending, - // 'archived' => $statuslabel->archived, - // ]; + public function testLostStatuslabelAdd() + { + $statuslabel = factory(Statuslabel::class)->states('lost')->make(); + $values = [ + 'name' => $statuslabel->name, + 'deployable' => $statuslabel->deployable, + 'pending' => $statuslabel->pending, + 'archived' => $statuslabel->archived, + ]; - // Statuslabel::create($values); - // $this->tester->seeRecord('status_labels', $values); - // } + Statuslabel::create($values); + $this->tester->seeRecord('status_labels', $values); + } } From 66c3f5432dd2f8005976347052492e208d4dba87 Mon Sep 17 00:00:00 2001 From: Azerothian Date: Tue, 24 Jul 2018 13:28:45 +1000 Subject: [PATCH 05/13] implemented specific seat checkout (#5887) --- app/Http/Controllers/LicensesController.php | 33 ++++++++++++------- .../views/partials/bootstrap-table.blade.php | 2 +- routes/web/licenses.php | 4 +-- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/app/Http/Controllers/LicensesController.php b/app/Http/Controllers/LicensesController.php index 04ee93d06..98a946197 100755 --- a/app/Http/Controllers/LicensesController.php +++ b/app/Http/Controllers/LicensesController.php @@ -265,31 +265,40 @@ class LicensesController extends Controller * @author [A. Gianotto] [] * @since [v1.0] * @param Request $request + * @param int $licenseId * @param int $seatId * @return \Illuminate\Http\RedirectResponse */ - public function postCheckout(Request $request, $licenseId) + public function postCheckout(Request $request, $licenseId, $seatId = null) { // Check that the license is valid - if ($license = License::where('id',$licenseId)->first()) { - + if ($license = License::where('id', $licenseId)->first()) { + // If the license is valid, check that there is an available seat if ($license->getAvailSeatsCountAttribute() < 1) { return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license'); } - - // Get the next available seat for this license - $next = $license->freeSeat(); - - if (!$next) { - return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license'); + if (!$seatId) { + // Get the next available seat for this license + $next = $license->freeSeat(); + if (!$next) { + return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license'); + } + if (!$licenseSeat = LicenseSeat::where('id', '=', $next->id)->first()) { + return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license'); + } + } else { + $licenseSeat = LicenseSeat::where('id', '=', $seatId)->first(); + if (!$licenseSeat) { + return redirect()->route('licenses.index')->with('error', 'License seat is not available for checkout'); + } } + - if (!$licenseSeat = LicenseSeat::where('id', '=', $next->id)->first()) { - return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license'); - } + + $this->authorize('checkout', $license); diff --git a/resources/views/partials/bootstrap-table.blade.php b/resources/views/partials/bootstrap-table.blade.php index c2cb62d85..291ebc531 100644 --- a/resources/views/partials/bootstrap-table.blade.php +++ b/resources/views/partials/bootstrap-table.blade.php @@ -277,7 +277,7 @@ function licenseSeatInOutFormatter(value, row) { // The user is allowed to check the license seat out and it's available if ((row.available_actions.checkout == true) && (row.user_can_checkout == true) && ((!row.asset_id) && (!row.assigned_to))) { - return '{{ trans('general.checkout') }}'; + return '{{ trans('general.checkout') }}'; } else { return '{{ trans('general.checkin') }}'; } diff --git a/routes/web/licenses.php b/routes/web/licenses.php index d6409fa20..2117d5229 100644 --- a/routes/web/licenses.php +++ b/routes/web/licenses.php @@ -11,12 +11,12 @@ Route::group([ 'prefix' => 'licenses', 'middleware' => ['auth'] ], function () { 'as' => 'licenses.freecheckout', 'uses' => 'LicensesController@getFreeLicense' ]); - Route::get('{licenseId}/checkout', [ + Route::get('{licenseId}/checkout/{seatId?}', [ 'as' => 'licenses.checkout', 'uses' => 'LicensesController@getCheckout' ]); Route::post( - '{licenseId}/checkout', + '{licenseId}/checkout/{seatId?}', [ 'as' => 'licenses.checkout', 'uses' => 'LicensesController@postCheckout' ] ); Route::get('{licenseId}/checkin/{backto?}', [ From ef1e8df00110a060f16c828d964ac74109eb07a4 Mon Sep 17 00:00:00 2001 From: Earl Ramirez Date: Tue, 24 Jul 2018 11:40:04 +0800 Subject: [PATCH 06/13] Disable file browsing (#5922) * Added cron to list of packages * Disable file browsing from the public directory --- Dockerfile | 1 + snipeit.sh | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index acd69f5a3..f13fa9ea6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,6 +20,7 @@ vim \ git \ cron \ mysql-client \ +cron \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* diff --git a/snipeit.sh b/snipeit.sh index 0a28e2940..48be3a979 100755 --- a/snipeit.sh +++ b/snipeit.sh @@ -134,7 +134,7 @@ create_virtualhost () { echo " " echo " Allow From All" echo " AllowOverride All" - echo " Options +Indexes" + echo " Options -Indexes" echo " " echo "" echo " DocumentRoot $APP_PATH/public" From 152d985ebcef22cc49b0f1d3b852a3bf199f5497 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 24 Jul 2018 12:08:26 -0700 Subject: [PATCH 07/13] Add @Azerothian as a contributor --- .all-contributorsrc | 9 +++++++++ README.md | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index d2c1088b7..4e9f44a08 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1641,6 +1641,15 @@ "contributions": [ "code" ] + }, + { + "login": "Azerothian", + "name": "Azerothian", + "avatar_url": "https://avatars1.githubusercontent.com/u/264022?v=4", + "profile": "https://www.illisian.com.au", + "contributions": [ + "code" + ] } ] } diff --git a/README.md b/README.md index 9e1dc7e1c..8b3e886dc 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![Build Status](https://travis-ci.org/snipe/snipe-it.svg?branch=master)](https://travis-ci.org/snipe/snipe-it) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/snipe-it/localized.svg)](https://crowdin.com/project/snipe-it) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/snipe/snipe-it?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Docker Pulls](https://img.shields.io/docker/pulls/snipe/snipe-it.svg)](https://hub.docker.com/r/snipe/snipe-it/) [![Twitter Follow](https://img.shields.io/twitter/follow/snipeitapp.svg?style=social)](https://twitter.com/snipeitapp) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/553ce52037fc43ea99149785afcfe641)](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&utm_medium=referral&utm_content=snipe/snipe-it&utm_campaign=Badge_Grade) -[![All Contributors](https://img.shields.io/badge/all_contributors-179-orange.svg?style=flat-square)](#contributors) [![Open Source Helpers](https://www.codetriage.com/snipe/snipe-it/badges/users.svg)](https://www.codetriage.com/snipe/snipe-it) +[![All Contributors](https://img.shields.io/badge/all_contributors-180-orange.svg?style=flat-square)](#contributors) [![Open Source Helpers](https://www.codetriage.com/snipe/snipe-it/badges/users.svg)](https://www.codetriage.com/snipe/snipe-it) ## Snipe-IT - Open Source Asset Management System @@ -95,7 +95,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken | [
Martin Stub](http://martinstub.dk)
[๐ŸŒ](#translation-stubben "Translation") | [
Meyer Flavio](https://github.com/meyerf99)
[๐ŸŒ](#translation-meyerf99 "Translation") | [
Micael Rodrigues](https://github.com/MicaelRodrigues)
[๐ŸŒ](#translation-MicaelRodrigues "Translation") | [
Mikael Rasmussen](http://rubixy.com/)
[๐ŸŒ](#translation-mikaelssen "Translation") | [
IxFail](https://github.com/IxFail)
[๐ŸŒ](#translation-IxFail "Translation") | [
Mohammed Fota](http://www.mohammedfota.com)
[๐ŸŒ](#translation-MohammedFota "Translation") | [
Moayad Alserihi](https://github.com/omego)
[๐ŸŒ](#translation-omego "Translation") | | [
saymd](https://github.com/saymd)
[๐ŸŒ](#translation-saymd "Translation") | [
Patrik Larsson](https://nordsken.se)
[๐ŸŒ](#translation-pooot "Translation") | [
drcryo](https://github.com/drcryo)
[๐ŸŒ](#translation-drcryo "Translation") | [
pawel1615](https://github.com/pawel1615)
[๐ŸŒ](#translation-pawel1615 "Translation") | [
bodrovics](https://github.com/bodrovics)
[๐ŸŒ](#translation-bodrovics "Translation") | [
priatna](https://github.com/priatna)
[๐ŸŒ](#translation-priatna "Translation") | [
Fan Jiang](https://amayume.net)
[๐ŸŒ](#translation-ProfFan "Translation") | | [
ragnarcx](https://github.com/ragnarcx)
[๐ŸŒ](#translation-ragnarcx "Translation") | [
Rein van Haaren](http://www.reinvanhaaren.nl/)
[๐ŸŒ](#translation-reinvanhaaren "Translation") | [
Teguh Dwicaksana](http://dheche.songolimo.net)
[๐ŸŒ](#translation-dheche "Translation") | [
fraccie](https://github.com/FRaccie)
[๐ŸŒ](#translation-FRaccie "Translation") | [
vinzruzell](https://github.com/vinzruzell)
[๐ŸŒ](#translation-vinzruzell "Translation") | [
Kevin Austin](http://kevinaustin.com)
[๐ŸŒ](#translation-vipsystem "Translation") | [
Wira Sandy](http://azuraweb.xyz)
[๐ŸŒ](#translation-wira-sandy "Translation") | -| [
ะ˜ะปัŒั](https://github.com/GrayHoax)
[๐ŸŒ](#translation-GrayHoax "Translation") | [
GodUseVPN](https://github.com/godusevpn)
[๐ŸŒ](#translation-godusevpn "Translation") | [
ๅ‘จๅ‘จ](https://github.com/EngrZhou)
[๐ŸŒ](#translation-EngrZhou "Translation") | [
Sam](https://github.com/takuy)
[๐Ÿ’ป](https://github.com/snipe/snipe-it/commits?author=takuy "Code") | +| [
ะ˜ะปัŒั](https://github.com/GrayHoax)
[๐ŸŒ](#translation-GrayHoax "Translation") | [
GodUseVPN](https://github.com/godusevpn)
[๐ŸŒ](#translation-godusevpn "Translation") | [
ๅ‘จๅ‘จ](https://github.com/EngrZhou)
[๐ŸŒ](#translation-EngrZhou "Translation") | [
Sam](https://github.com/takuy)
[๐Ÿ’ป](https://github.com/snipe/snipe-it/commits?author=takuy "Code") | [
Azerothian](https://www.illisian.com.au)
[๐Ÿ’ป](https://github.com/snipe/snipe-it/commits?author=Azerothian "Code") | This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome! From 227dc7e81d4d3f97f7d35c938547c33a0b615d78 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 24 Jul 2018 12:09:30 -0700 Subject: [PATCH 08/13] Save model display setting - fix for issue in #5301 --- app/Http/Controllers/SettingsController.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/Http/Controllers/SettingsController.php b/app/Http/Controllers/SettingsController.php index 69d6c7106..962decb07 100755 --- a/app/Http/Controllers/SettingsController.php +++ b/app/Http/Controllers/SettingsController.php @@ -815,6 +815,12 @@ class SettingsController extends Controller $setting->labels_display_tag = 0; } + if ($request->has('labels_display_model')) { + $setting->labels_display_model = 1; + } else { + $setting->labels_display_model = 0; + } + if ($setting->save()) { return redirect()->route('settings.index') ->with('success', trans('admin/settings/message.update.success')); From f4cfb31bf41fdd1c2326802a2f7c8a7709e38cbd Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 24 Jul 2018 12:09:57 -0700 Subject: [PATCH 09/13] Use request object --- app/Http/Controllers/SettingsController.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/Http/Controllers/SettingsController.php b/app/Http/Controllers/SettingsController.php index 962decb07..9338472e2 100755 --- a/app/Http/Controllers/SettingsController.php +++ b/app/Http/Controllers/SettingsController.php @@ -791,25 +791,25 @@ class SettingsController extends Controller - if (Input::has('labels_display_name')) { + if ($request->has('labels_display_name')) { $setting->labels_display_name = 1; } else { $setting->labels_display_name = 0; } - if (Input::has('labels_display_serial')) { + if ($request->has('labels_display_serial')) { $setting->labels_display_serial = 1; } else { $setting->labels_display_serial = 0; } - if (Input::has('labels_display_tag')) { + if ($request->has('labels_display_tag')) { $setting->labels_display_tag = 1; } else { $setting->labels_display_tag = 0; - } + } - if (Input::has('labels_display_tag')) { + if ($request->has('labels_display_tag')) { $setting->labels_display_tag = 1; } else { $setting->labels_display_tag = 0; From 8ecceeacda583a21adc473e5d26e179468794dce Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 24 Jul 2018 12:41:58 -0700 Subject: [PATCH 10/13] Fixed weird display for self options --- resources/views/groups/edit.blade.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/resources/views/groups/edit.blade.php b/resources/views/groups/edit.blade.php index ccdc394cd..8149d6450 100755 --- a/resources/views/groups/edit.blade.php +++ b/resources/views/groups/edit.blade.php @@ -98,12 +98,12 @@ @else -

{{ $area . ': ' . $localPermission['label'] }}

-

{{ $localPermission['note'] }}

+ @@ -135,9 +135,7 @@ @endif @endforeach - - - + @endif @endforeach From 376eb52f0024bf9e22e378d3ba0d95a83efef41f Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 24 Jul 2018 12:42:16 -0700 Subject: [PATCH 11/13] =?UTF-8?q?Fixed=20#5938=20-=20added=20=E2=80=9Cself?= =?UTF-8?q?=20location=20edit=E2=80=9D=20as=20permission?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/ProfileController.php | 20 +++++++++++++------- app/Http/Controllers/SettingsController.php | 6 +++++- app/Providers/AuthServiceProvider.php | 4 ++++ config/permissions.php | 7 +++++++ resources/views/account/profile.blade.php | 14 ++++++++++++-- 5 files changed, 41 insertions(+), 10 deletions(-) diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php index 72fde2fe9..492b65db0 100755 --- a/app/Http/Controllers/ProfileController.php +++ b/app/Http/Controllers/ProfileController.php @@ -45,15 +45,21 @@ class ProfileController extends Controller { $user = Auth::user(); - $user->first_name = Input::get('first_name'); - $user->last_name = Input::get('last_name'); - $user->website = Input::get('website'); - $user->location_id = Input::get('location_id'); - $user->gravatar = Input::get('gravatar'); - $user->locale = Input::get('locale'); + $user->first_name = $request->input('first_name'); + $user->last_name = $request->input('last_name'); + $user->website = $request->input('website'); + $user->gravatar = $request->input('gravatar'); + + if (!config('app.lock_passwords')) { + $user->locale = $request->input('locale', 'en'); + } if ((Gate::allows('self.two_factor')) && ((Setting::getSettings()->two_factor_enabled=='1') && (!config('app.lock_passwords')))) { - $user->two_factor_optin = Input::get('two_factor_optin', '0'); + $user->two_factor_optin = $request->input('two_factor_optin', '0'); + } + + if (Gate::allows('self.edit_location') && (!config('app.lock_passwords'))) { + $user->location_id = $request->input('location_id'); } if (Input::file('avatar')) { diff --git a/app/Http/Controllers/SettingsController.php b/app/Http/Controllers/SettingsController.php index 9338472e2..ee9d02b5b 100755 --- a/app/Http/Controllers/SettingsController.php +++ b/app/Http/Controllers/SettingsController.php @@ -169,7 +169,11 @@ class SettingsController extends Controller $settings->alerts_enabled = 1; $settings->pwd_secure_min = 10; $settings->brand = 1; - $settings->locale = $request->input('locale', 'en'); + + if (!config('app.lock_passwords')) { + $settings->locale = $request->input('locale', 'en'); + } + $settings->default_currency = $request->input('default_currency', "USD"); $settings->user_id = 1; $settings->email_domain = $request->input('email_domain'); diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 4ea08934c..bff39fbf1 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -135,6 +135,10 @@ class AuthServiceProvider extends ServiceProvider return $user->hasAccess('self.api'); }); + Gate::define('self.edit_location', function($user) { + return $user->hasAccess('self.edit_location'); + }); + Gate::define('backend.interact', function ($user) { return $user->can('view', Statuslabel::class) || $user->can('view', AssetModel::class) diff --git a/config/permissions.php b/config/permissions.php index 0d432b8c9..295039180 100644 --- a/config/permissions.php +++ b/config/permissions.php @@ -571,6 +571,13 @@ return array( 'display' => true, ), + array( + 'permission' => 'self.edit_location', + 'label' => 'Profile Edit Location', + 'note' => 'The user may update their own location in their profile. Note that this is not affected by any additional Users permissions you grant to this user or group.', + 'display' => true, + ), + ), diff --git a/resources/views/account/profile.blade.php b/resources/views/account/profile.blade.php index 1d0032ed7..18a828703 100755 --- a/resources/views/account/profile.blade.php +++ b/resources/views/account/profile.blade.php @@ -37,19 +37,29 @@ + @can('self.edit_location') @include ('partials.forms.edit.location-profile-select', ['translated_name' => trans('general.location')]) + @endcan +
- {!! Form::locales('locale', Input::old('locale', $user->locale), 'select2') !!} - {!! $errors->first('locale', ':message') !!} + + @if (!config('app.lock_passwords')) + {!! Form::locales('locale', Input::old('locale', $user->locale), 'select2') !!} + {!! $errors->first('locale', ':message') !!} + @else +

{{ trans('general.feature_disabled') }}

+ @endif +
+
From ed78a4b8a01c9c15c726ee2d226510c6a4f3691a Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 24 Jul 2018 13:28:59 -0700 Subject: [PATCH 12/13] Fixed activated issue for strict mode --- app/Http/Controllers/UsersController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/UsersController.php b/app/Http/Controllers/UsersController.php index 7afebbb94..53036414b 100755 --- a/app/Http/Controllers/UsersController.php +++ b/app/Http/Controllers/UsersController.php @@ -112,7 +112,7 @@ class UsersController extends Controller $user->last_name = $request->input('last_name'); $user->locale = $request->input('locale'); $user->employee_num = $request->input('employee_num'); - $user->activated = $request->input('activated', $user->activated); + $user->activated = $request->input('activated', 0); $user->jobtitle = $request->input('jobtitle'); $user->phone = $request->input('phone'); $user->location_id = $request->input('location_id', null); From e320d2ba05225635ae47852a66d8522f53d39c7d Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 24 Jul 2018 13:37:02 -0700 Subject: [PATCH 13/13] Fixed #5944 - added logo option for print-assets page (#5950) --- app/Http/Controllers/SettingsController.php | 12 +++---- ..._07_24_154348_add_logo_to_print_assets.php | 34 +++++++++++++++++++ resources/lang/en/admin/settings/general.php | 2 ++ resources/views/settings/branding.blade.php | 15 +++++++- resources/views/settings/general.blade.php | 2 +- resources/views/users/print.blade.php | 26 +++++++++++++- 6 files changed, 82 insertions(+), 9 deletions(-) create mode 100644 database/migrations/2018_07_24_154348_add_logo_to_print_assets.php diff --git a/app/Http/Controllers/SettingsController.php b/app/Http/Controllers/SettingsController.php index ee9d02b5b..7034186cc 100755 --- a/app/Http/Controllers/SettingsController.php +++ b/app/Http/Controllers/SettingsController.php @@ -169,11 +169,7 @@ class SettingsController extends Controller $settings->alerts_enabled = 1; $settings->pwd_secure_min = 10; $settings->brand = 1; - - if (!config('app.lock_passwords')) { - $settings->locale = $request->input('locale', 'en'); - } - + $settings->locale = $request->input('locale', 'en'); $settings->default_currency = $request->input('default_currency', "USD"); $settings->user_id = 1; $settings->email_domain = $request->input('email_domain'); @@ -405,6 +401,8 @@ class SettingsController extends Controller $setting->footer_text = $request->input('footer_text'); $setting->skin = $request->input('skin'); $setting->show_url_in_emails = $request->input('show_url_in_emails', '0'); + $setting->logo_print_assets = $request->input('logo_print_assets', '0'); + // Only allow the site name and CSS to be changed if lock_passwords is false @@ -541,7 +539,9 @@ class SettingsController extends Controller return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error')); } - $setting->locale = $request->input('locale', 'en'); + if (!config('app.lock_passwords')) { + $setting->locale = $request->input('locale', 'en'); + } $setting->default_currency = $request->input('default_currency', '$'); $setting->date_display_format = $request->input('date_display_format'); $setting->time_display_format = $request->input('time_display_format'); diff --git a/database/migrations/2018_07_24_154348_add_logo_to_print_assets.php b/database/migrations/2018_07_24_154348_add_logo_to_print_assets.php new file mode 100644 index 000000000..70ffe193c --- /dev/null +++ b/database/migrations/2018_07_24_154348_add_logo_to_print_assets.php @@ -0,0 +1,34 @@ +boolean('logo_print_assets')->default('0'); + }); + + + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('settings', function (Blueprint $table) { + $table->dropColumn('logo_print_assets'); + }); + } +} diff --git a/resources/lang/en/admin/settings/general.php b/resources/lang/en/admin/settings/general.php index a6abf8bc7..252589705 100644 --- a/resources/lang/en/admin/settings/general.php +++ b/resources/lang/en/admin/settings/general.php @@ -88,6 +88,8 @@ return array( 'login_remote_user_custom_logout_url_text' => 'Custom logout URL', 'login_remote_user_custom_logout_url_help' => 'If a url is provided here, users will get redirected to this URL after the user logs out of Snipe-IT. This is useful to close the user sessions of your Authentication provider correctly.', 'logo' => 'Logo', + 'logo_print_assets' => 'Use in Print', + 'logo_print_assets_help' => 'Use branding on printable asset lists ', 'full_multiple_companies_support_help_text' => 'Restricting users (including admins) assigned to companies to their company\'s assets.', 'full_multiple_companies_support_text' => 'Full Multiple Companies Support', 'show_in_model_list' => 'Show in Model Dropdowns', diff --git a/resources/views/settings/branding.blade.php b/resources/views/settings/branding.blade.php index c01fae178..d2ffd400f 100644 --- a/resources/views/settings/branding.blade.php +++ b/resources/views/settings/branding.blade.php @@ -93,7 +93,20 @@ {!! $errors->first('brand', ':message') !!}
- + + +
+
+ {{ Form::label('logo_print_assets', trans('admin/settings/general.logo_print_assets')) }} +
+
+ {{ Form::checkbox('logo_print_assets', '1', Input::old('logo_print_assets', $setting->logo_print_assets),array('class' => 'minimal')) }} + {{ trans('admin/settings/general.logo_print_assets_help') }} +
+
+ + +
{{ Form::label('show_url_in_emails', trans('admin/settings/general.show_url_in_emails')) }} diff --git a/resources/views/settings/general.blade.php b/resources/views/settings/general.blade.php index 174d173af..41fe09ea5 100644 --- a/resources/views/settings/general.blade.php +++ b/resources/views/settings/general.blade.php @@ -118,7 +118,7 @@
{{ Form::checkbox('load_remote', '1', Input::old('load_remote', $setting->load_remote),array('class' => 'minimal')) }} - {{ trans('admin/settings/general.load_remote_help_text') }} +

{{ trans('admin/settings/general.load_remote_help_text') }}

diff --git a/resources/views/users/print.blade.php b/resources/views/users/print.blade.php index 236797833..974f32d99 100644 --- a/resources/views/users/print.blade.php +++ b/resources/views/users/print.blade.php @@ -22,10 +22,34 @@ padding: 3px; font-size: 12px; } + + .print-logo { + max-height: 40px; + } + -

Assigned to {{ $show_user->present()->fullName() }}

+ +@if ($snipeSettings->logo_print_assets=='1') + @if ($snipeSettings->brand == '3') + +

+ @if ($snipeSettings->logo!='') + + @endif + {{ $snipeSettings->site_name }} +

+ @elseif ($snipeSettings->brand == '2') + @if ($snipeSettings->logo!='') + + @endif + @else +

{{ $snipeSettings->site_name }}

+ @endif +@endif + +

Assigned to {{ $show_user->present()->fullName() }}

@if ($assets->count() > 0) @php