Merge remote-tracking branch 'origin/develop'

This commit is contained in:
snipe 2021-08-14 14:09:31 -07:00
commit 29c584289f
21 changed files with 157 additions and 32 deletions

View file

@ -55,11 +55,11 @@ Since the release of the JSON REST API, several third-party developers have been
- [Python Module](https://github.com/jbloomer/SnipeIT-PythonAPI) by [@jbloomer](https://github.com/jbloomer) - [Python Module](https://github.com/jbloomer/SnipeIT-PythonAPI) by [@jbloomer](https://github.com/jbloomer)
- [SnipeSharp - .NET module in C#](https://github.com/barrycarey/SnipeSharp) by [@barrycarey](https://github.com/barrycarey) - [SnipeSharp - .NET module in C#](https://github.com/barrycarey/SnipeSharp) by [@barrycarey](https://github.com/barrycarey)
- [InQRy](https://github.com/Microsoft/InQRy) by [@Microsoft](https://github.com/Microsoft) - [InQRy -unmaintained-](https://github.com/Microsoft/InQRy) by [@Microsoft](https://github.com/Microsoft)
- [SnipeitPS](https://github.com/snazy2000/SnipeitPS) by [@snazy2000](https://github.com/snazy2000) - Powershell API Wrapper for Snipe-it - [SnipeitPS](https://github.com/snazy2000/SnipeitPS) by [@snazy2000](https://github.com/snazy2000) - Powershell API Wrapper for Snipe-it
- [jamf2snipe](https://github.com/ParadoxGuitarist/jamf2snipe) by [@ParadoxGuitarist](https://github.com/ParadoxGuitarist) - Python script to sync assets between a JAMFPro instance and a Snipe-IT instance - [jamf2snipe](https://github.com/ParadoxGuitarist/jamf2snipe) by [@ParadoxGuitarist](https://github.com/ParadoxGuitarist) - Python script to sync assets between a JAMFPro instance and a Snipe-IT instance
- [Marksman](https://github.com/Scope-IT/marksman) - A Windows agent for Snipe-IT - [Marksman](https://github.com/Scope-IT/marksman) - A Windows agent for Snipe-IT
- [Snipe-IT plugin for Jira Service Desk (beta)](https://marketplace.atlassian.com/apps/1220379/snipe-it-for-jira-service-desk-beta?hosting=cloud&tab=overview) - for the upcoming Snipe-IT v5 only - [Snipe-IT plugin for Jira Service Desk)](https://marketplace.atlassian.com/apps/1220964/snipe-it-for-jira)
- [Python 3 CSV importer](https://github.com/gastamper/snipeit-csvimporter) - allows importing assets into Snipe-IT based on Item Name rather than Asset Tag. - [Python 3 CSV importer](https://github.com/gastamper/snipeit-csvimporter) - allows importing assets into Snipe-IT based on Item Name rather than Asset Tag.
- [Snipe-IT Kubernetes Helm Chart](https://github.com/t3n/helm-charts/tree/master/snipeit) - For more information, [click here](https://hub.helm.sh/charts/t3n/snipeit). - [Snipe-IT Kubernetes Helm Chart](https://github.com/t3n/helm-charts/tree/master/snipeit) - For more information, [click here](https://hub.helm.sh/charts/t3n/snipeit).
- [Snipe-IT Bulk Edit](https://github.com/bricelabelle/snipe-it-bulkedit) - Google Script files to use Google Sheets as a bulk checkout/checkin/edit tool for Snipe-it. - [Snipe-IT Bulk Edit](https://github.com/bricelabelle/snipe-it-bulkedit) - Google Script files to use Google Sheets as a bulk checkout/checkin/edit tool for Snipe-it.

View file

@ -51,6 +51,10 @@ class AccessoriesController extends Controller
$accessories->where('supplier_id','=',$request->input('supplier_id')); $accessories->where('supplier_id','=',$request->input('supplier_id'));
} }
if ($request->filled('location_id')) {
$accessories->where('location_id','=',$request->input('location_id'));
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which // Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items. // case we override with the actual count, so we should return 0 items.
$offset = (($accessories) && ($request->get('offset') > $accessories->count())) ? $accessories->count() : $request->get('offset', 0); $offset = (($accessories) && ($request->get('offset') > $accessories->count())) ? $accessories->count() : $request->get('offset', 0);
@ -167,9 +171,13 @@ class AccessoriesController extends Controller
if ($request->filled('search')) { if ($request->filled('search')) {
$accessory_users = $accessory->users() $accessory_users = $accessory->users()
->where('first_name', 'like', '%'.$request->input('search').'%') ->where(function ($query) use ($request) {
->orWhere('last_name', 'like', '%'.$request->input('search').'%') $search_str = '%' . $request->input('search') . '%';
->get(); $query->where('first_name', 'like', $search_str)
->orWhere('last_name', 'like', $search_str)
->orWhere('note', 'like', $search_str);
})
->get();
$total = $accessory_users->count(); $total = $accessory_users->count();
} }

View file

@ -9,6 +9,7 @@ use App\Http\Requests\AssetCheckoutRequest;
use App\Http\Transformers\AssetsTransformer; use App\Http\Transformers\AssetsTransformer;
use App\Http\Transformers\LicensesTransformer; use App\Http\Transformers\LicensesTransformer;
use App\Http\Transformers\SelectlistTransformer; use App\Http\Transformers\SelectlistTransformer;
use App\Models\Actionlog;
use App\Models\Asset; use App\Models\Asset;
use App\Models\AssetModel; use App\Models\AssetModel;
use App\Models\Company; use App\Models\Company;
@ -640,6 +641,39 @@ class AssetsController extends Controller
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200); return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
} }
/**
* Restore a soft-deleted asset.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v5.1.18]
* @return JsonResponse
*/
public function restore($assetId = null)
{
// Get asset information
$asset = Asset::withTrashed()->find($assetId);
$this->authorize('delete', $asset);
if (isset($asset->id)) {
// Restore the asset
Asset::withTrashed()->where('id', $assetId)->restore();
$logaction = new Actionlog();
$logaction->item_type = Asset::class;
$logaction->item_id = $asset->id;
$logaction->created_at = date("Y-m-d H:i:s");
$logaction->user_id = Auth::user()->id;
$logaction->logaction('restored');
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/hardware/message.restore.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
}
/** /**

View file

@ -46,6 +46,10 @@ class ConsumablesController extends Controller
$consumables->where('manufacturer_id','=',$request->input('manufacturer_id')); $consumables->where('manufacturer_id','=',$request->input('manufacturer_id'));
} }
if ($request->filled('location_id')) {
$consumables->where('location_id','=',$request->input('location_id'));
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which // Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items. // case we override with the actual count, so we should return 0 items.

View file

@ -20,9 +20,9 @@ class DepreciationsController extends Controller
public function index(Request $request) public function index(Request $request)
{ {
$this->authorize('view', Depreciation::class); $this->authorize('view', Depreciation::class);
$allowed_columns = ['id','name','months','created_at']; $allowed_columns = ['id','name','months','depreciation_min','created_at'];
$depreciations = Depreciation::select('id','name','months','user_id','created_at','updated_at'); $depreciations = Depreciation::select('id','name','months','depreciation_min','user_id','created_at','updated_at');
if ($request->filled('search')) { if ($request->filled('search')) {
$depreciations = $depreciations->TextSearch($request->input('search')); $depreciations = $depreciations->TextSearch($request->input('search'));

View file

@ -61,7 +61,7 @@ class ForgotPasswordController extends Controller
$request->validate([ $request->validate([
'username' => ['required', 'max:255'], 'username' => ['required', 'max:255'],
]); ]);
/** /**
@ -71,13 +71,21 @@ class ForgotPasswordController extends Controller
* Once we have attempted to send the link, we will examine the response * Once we have attempted to send the link, we will examine the response
* then see the message we need to show to the user. Finally, we'll send out a proper response. * then see the message we need to show to the user. Finally, we'll send out a proper response.
*/ */
$response = $this->broker()->sendResetLink(
array_merge( $response = null;
$request->only('username'),
['activated' => '1'], try {
['ldap_import' => '0'] $response = $this->broker()->sendResetLink(
) array_merge(
); $request->only('username'),
['activated' => '1'],
['ldap_import' => '0']
)
);
} catch(\Exception $e) {
\Log::info('Password reset attempt: User '.$request->input('username').'failed with exception: '.$e );
}
if ($response === \Password::RESET_LINK_SENT) { if ($response === \Password::RESET_LINK_SENT) {
\Log::info('Password reset attempt: User '.$request->input('username').' WAS found, password reset sent'); \Log::info('Password reset attempt: User '.$request->input('username').' WAS found, password reset sent');

View file

@ -69,6 +69,7 @@ class DepreciationsController extends Controller
// Depreciation data // Depreciation data
$depreciation->name = $request->input('name'); $depreciation->name = $request->input('name');
$depreciation->months = $request->input('months'); $depreciation->months = $request->input('months');
$depreciation->depreciations_min= $request->input('depreciation_min');
$depreciation->user_id = Auth::id(); $depreciation->user_id = Auth::id();
// Was the asset created? // Was the asset created?
@ -125,8 +126,9 @@ class DepreciationsController extends Controller
$this->authorize('update', $depreciation); $this->authorize('update', $depreciation);
// Depreciation data // Depreciation data
$depreciation->name = $request->input('name'); $depreciation->name = $request->input('name');
$depreciation->months = $request->input('months'); $depreciation->months = $request->input('months');
$depreciation->depreciation_min = $request->input('depreciation_min');
// Was the asset created? // Was the asset created?
if ($depreciation->save()) { if ($depreciation->save()) {

View file

@ -24,6 +24,7 @@ class DepreciationsTransformer
'id' => (int) $depreciation->id, 'id' => (int) $depreciation->id,
'name' => e($depreciation->name), 'name' => e($depreciation->name),
'months' => $depreciation->months . ' '. trans('general.months'), 'months' => $depreciation->months . ' '. trans('general.months'),
'depreciation_min' => $depreciation->depreciation_min,
'created_at' => Helper::getFormattedDateObject($depreciation->created_at, 'datetime'), 'created_at' => Helper::getFormattedDateObject($depreciation->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($depreciation->updated_at, 'datetime'), 'updated_at' => Helper::getFormattedDateObject($depreciation->updated_at, 'datetime'),
]; ];

View file

@ -14,7 +14,7 @@ class AccessoryImporter extends ItemImporter
protected function handle($row) protected function handle($row)
{ {
parent::handle($row); // TODO: Change the autogenerated stub parent::handle($row); // TODO: Change the autogenerated stub
$this->createAccessoryIfNotExists(); $this->createAccessoryIfNotExists($row);
} }
/** /**
@ -23,7 +23,7 @@ class AccessoryImporter extends ItemImporter
* @author Daniel Melzter * @author Daniel Melzter
* @since 3.0 * @since 3.0
*/ */
public function createAccessoryIfNotExists() public function createAccessoryIfNotExists($row)
{ {
$accessory = Accessory::where('name', $this->item['name'])->first(); $accessory = Accessory::where('name', $this->item['name'])->first();
if ($accessory) { if ($accessory) {
@ -33,12 +33,14 @@ class AccessoryImporter extends ItemImporter
} }
$this->log('Updating Accessory'); $this->log('Updating Accessory');
$this->item['model_number'] = $this->findCsvMatch($row, "model_number");
$accessory->update($this->sanitizeItemForUpdating($accessory)); $accessory->update($this->sanitizeItemForUpdating($accessory));
$accessory->save(); $accessory->save();
return; return;
} }
$this->log("No Matching Accessory, Creating a new one"); $this->log("No Matching Accessory, Creating a new one");
$accessory = new Accessory(); $accessory = new Accessory();
$this->item['model_number'] = $this->findCsvMatch($row, "model_number");
$accessory->fill($this->sanitizeItemForStoring($accessory)); $accessory->fill($this->sanitizeItemForStoring($accessory));
//FIXME: this disables model validation. Need to find a way to avoid double-logs without breaking everything. //FIXME: this disables model validation. Need to find a way to avoid double-logs without breaking everything.

View file

@ -226,26 +226,26 @@ $factory->state(App\Models\AssetModel::class, 'tab3-model', function ($faker) {
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
*/ */
$factory->state(App\Models\AssetModel::class, 'iphone6s-model', function ($faker) { $factory->state(App\Models\AssetModel::class, 'iphone11-model', function ($faker) {
return [ return [
'name' => 'iPhone 6s', 'name' => 'iPhone 11',
'category_id' => 4, 'category_id' => 4,
'manufacturer_id' => 1, 'manufacturer_id' => 1,
'eol' => '12', 'eol' => '12',
'depreciation_id' => 3, 'depreciation_id' => 3,
'image' => 'iphone6.jpg', 'image' => 'iphone11.jpeg',
'fieldset_id' => 1, 'fieldset_id' => 1,
]; ];
}); });
$factory->state(App\Models\AssetModel::class, 'iphone7-model', function ($faker) { $factory->state(App\Models\AssetModel::class, 'iphone12-model', function ($faker) {
return [ return [
'name' => 'iPhone 7', 'name' => 'iPhone 12',
'category_id' => 4, 'category_id' => 4,
'manufacturer_id' => 1, 'manufacturer_id' => 1,
'eol' => '12', 'eol' => '12',
'depreciation_id' => 1, 'depreciation_id' => 1,
'image' => 'iphone7.jpg', 'image' => 'iphone12.jpeg',
'fieldset_id' => 1, 'fieldset_id' => 1,
]; ];
}); });

View file

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddDepreciationMinimumValue extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('depreciations', function (Blueprint $table) {
$table->decimal('depreciation_min', 8,2)->after('months')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('depreciations', function (Blueprint $table) {
$table->dropColumn('depreciation_min');
});
}
}

View file

@ -33,8 +33,8 @@ class AssetModelSeeder extends Seeder
factory(AssetModel::class, 1)->states('tab3-model')->create(); // 14 factory(AssetModel::class, 1)->states('tab3-model')->create(); // 14
// Phones // Phones
factory(AssetModel::class, 1)->states('iphone6s-model')->create(); // 15 factory(AssetModel::class, 1)->states('iphone11-model')->create(); // 15
factory(AssetModel::class, 1)->states('iphone7-model')->create(); // 16 factory(AssetModel::class, 1)->states('iphone12-model')->create(); // 16
// Displays // Displays
factory(AssetModel::class, 1)->states('ultrafine')->create(); // 17 factory(AssetModel::class, 1)->states('ultrafine')->create(); // 17

10
package-lock.json generated
View file

@ -11629,7 +11629,8 @@
"picomatch": { "picomatch": {
"version": "2.2.2", "version": "2.2.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
"optional": true
}, },
"pify": { "pify": {
"version": "2.3.0", "version": "2.3.0",
@ -14235,6 +14236,7 @@
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
"optional": true,
"requires": { "requires": {
"is-extglob": "^2.1.1" "is-extglob": "^2.1.1"
} }
@ -14248,7 +14250,8 @@
"normalize-path": { "normalize-path": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"optional": true
}, },
"readdirp": { "readdirp": {
"version": "3.4.0", "version": "3.4.0",
@ -18323,7 +18326,8 @@
"version": "2.2.2", "version": "2.2.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
"dev": true "dev": true,
"optional": true
}, },
"pify": { "pify": {
"version": "2.3.0", "version": "2.3.0",

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

View file

@ -141,6 +141,9 @@
{id: 'username', text: 'Username' }, {id: 'username', text: 'Username' },
{id: 'department', text: 'Department' }, {id: 'department', text: 'Department' },
], ],
accessories:[
{id: 'model_number', text: 'Model Number'},
],
assets: [ assets: [
{id: 'asset_tag', text: 'Asset Tag' }, {id: 'asset_tag', text: 'Asset Tag' },
{id: 'asset_model', text: 'Model Name' }, {id: 'asset_model', text: 'Model Name' },
@ -208,7 +211,10 @@
.concat(this.columnOptions.assets) .concat(this.columnOptions.assets)
.concat(this.columnOptions.customFields) .concat(this.columnOptions.customFields)
.sort(sorter); .sort(sorter);
case 'accessory':
return this.columnOptions.general
.concat(this.columnOptions.accessories)
.sort(sorter);
case 'consumable': case 'consumable':
return this.columnOptions.general return this.columnOptions.general
.concat(this.columnOptions.consumables) .concat(this.columnOptions.consumables)

View file

@ -8,5 +8,6 @@ return array(
'depreciation_name' => 'Depreciation Name', 'depreciation_name' => 'Depreciation Name',
'number_of_months' => 'Number of Months', 'number_of_months' => 'Number of Months',
'update' => 'Update Depreciation', 'update' => 'Update Depreciation',
'depreciation_min' => 'Minimum Value after Depreciation'
); );

View file

@ -22,5 +22,14 @@
</div> </div>
{!! $errors->first('months', '<span class="alert-msg" aria-hidden="true"><i class="fa fa-times" aria-hidden="true"></i> :message</span>') !!} {!! $errors->first('months', '<span class="alert-msg" aria-hidden="true"><i class="fa fa-times" aria-hidden="true"></i> :message</span>') !!}
</div> </div>
<!-- Depreciation Minimum -->
<div class="form-group {{ $errors->has('depreciation_min') ? ' has-error' : '' }}">
<label for="depreciation_min" class="col-md-3 control-label">
{{ trans('admin/depreciations/general.depreciation_min') }}
</label>
<div class="col-md-2" style="padding-left:0px">
<input class="form-control" name="depreciation_min" id="depreciation_min" value="{{ Request::old('depreciation_min', $item->depreciation_min) }}" style="width: 80px; margin-left:15px" />
</div>
{!! $errors->first('depreciation_min', '<span class="alert-msg" aria-hidden="true"><i class="fa fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>
@stop @stop

View file

@ -445,6 +445,20 @@ Route::group(['prefix' => 'v1','namespace' => 'Api', 'middleware' => 'auth:api']
] ]
); );
Route::post('{asset_id}/restore',
[
'as' => 'api.assets.restore',
'uses' => 'AssetsController@restore'
]
);
Route::post('{asset_id}/destroy',
[
'as' => 'api.assets.destroy',
'uses' => 'AssetsController@destroy'
]
);
}); });
/*--- Asset Maintenances API ---*/ /*--- Asset Maintenances API ---*/