2017-01-11 18:14:06 -08:00
< ? php
2021-06-10 13:15:52 -07:00
2017-01-11 18:14:06 -08:00
namespace App\Http\Controllers\Api ;
2021-06-08 11:16:13 -07:00
use App\Events\CheckoutableCheckedIn ;
2023-10-31 19:06:44 -07:00
use App\Http\Requests\StoreAssetRequest ;
2019-05-15 15:47:40 -07:00
use Illuminate\Support\Facades\Gate ;
2017-01-11 18:14:06 -08:00
use App\Helpers\Helper ;
2017-01-25 21:29:23 -08:00
use App\Http\Controllers\Controller ;
2017-11-27 21:17:16 -08:00
use App\Http\Requests\AssetCheckoutRequest ;
2017-01-25 21:29:23 -08:00
use App\Http\Transformers\AssetsTransformer ;
2021-09-01 17:33:39 -07:00
use App\Http\Transformers\DepreciationReportTransformer ;
2019-01-22 14:47:40 -08:00
use App\Http\Transformers\LicensesTransformer ;
2019-03-13 20:12:03 -07:00
use App\Http\Transformers\SelectlistTransformer ;
2021-08-14 14:06:15 -07:00
use App\Models\Actionlog ;
2017-01-11 18:14:06 -08:00
use App\Models\Asset ;
use App\Models\AssetModel ;
use App\Models\Company ;
use App\Models\CustomField ;
2019-01-22 14:47:40 -08:00
use App\Models\License ;
2017-01-11 18:14:06 -08:00
use App\Models\Location ;
2017-01-25 21:29:23 -08:00
use App\Models\Setting ;
2017-01-11 18:14:06 -08:00
use App\Models\User ;
2017-01-25 21:29:23 -08:00
use Auth ;
use Carbon\Carbon ;
use DB ;
2017-01-11 18:14:06 -08:00
use Illuminate\Http\Request ;
2021-06-29 02:26:24 -07:00
use App\Http\Requests\ImageUploadRequest ;
2017-01-25 21:29:23 -08:00
use Input ;
use Paginator ;
use Slack ;
use Str ;
use TCPDF ;
use Validator ;
2021-09-01 17:33:39 -07:00
use Route ;
2017-01-11 18:14:06 -08:00
2023-10-31 19:06:44 -07:00
2017-01-11 18:14:06 -08:00
/**
* This class controls all actions related to assets for
* the Snipe - IT Asset Management application .
*
* @ version v1 . 0
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
*/
class AssetsController extends Controller
{
2017-01-11 23:40:56 -08:00
/**
* Returns JSON listing of all assets
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ param int $assetId
* @ since [ v4 . 0 ]
2023-10-25 08:40:49 -07:00
* @ return \Illuminate\Http\JsonResponse
2017-01-11 23:40:56 -08:00
*/
2021-09-01 17:33:39 -07:00
public function index ( Request $request , $audit = null )
2017-01-11 18:14:06 -08:00
{
2018-01-11 15:17:34 -08:00
2022-01-15 12:01:19 -08:00
$filter_non_deprecable_assets = false ;
2021-09-01 17:33:39 -07:00
/**
* This looks MAD janky ( and it is ), but the AssetsController @ index does a LOT of heavy lifting throughout the
* app . This bit here just makes sure that someone without permission to view assets doesn ' t
* end up with priv escalations because they asked for a different endpoint .
*
* Since we never gave the specification for which transformer to use before , it should default
* gracefully to just use the AssetTransformer by default , which shouldn ' t break anything .
*
* It was either this mess , or repeating ALL of the searching and sorting and filtering code ,
* which would have been far worse of a mess . * sad face * - snipe ( Sept 1 , 2021 )
*/
if ( Route :: currentRouteName () == 'api.depreciation-report.index' ) {
2022-01-15 12:01:19 -08:00
$filter_non_deprecable_assets = true ;
2021-09-01 17:33:39 -07:00
$transformer = 'App\Http\Transformers\DepreciationReportTransformer' ;
$this -> authorize ( 'reports.view' );
} else {
$transformer = 'App\Http\Transformers\AssetsTransformer' ;
$this -> authorize ( 'index' , Asset :: class );
}
2018-01-17 19:18:48 -08:00
$settings = Setting :: getSettings ();
2017-01-13 11:41:00 -08:00
$allowed_columns = [
'id' ,
'name' ,
'asset_tag' ,
'serial' ,
'model_number' ,
'last_checkout' ,
'notes' ,
'expected_checkin' ,
'order_number' ,
'image' ,
'assigned_to' ,
'created_at' ,
2017-02-23 16:23:02 -08:00
'updated_at' ,
2017-01-13 11:41:00 -08:00
'purchase_date' ,
2017-10-31 07:05:15 -07:00
'purchase_cost' ,
2017-12-12 03:03:43 -08:00
'last_audit_date' ,
'next_audit_date' ,
2017-10-31 07:05:15 -07:00
'warranty_months' ,
2018-05-16 19:20:43 -07:00
'checkout_counter' ,
'checkin_counter' ,
'requests_counter' ,
2023-01-18 13:03:31 -08:00
'byod' ,
2023-01-22 00:56:44 -08:00
'asset_eol_date' ,
2017-01-13 11:41:00 -08:00
];
2021-06-10 13:15:52 -07:00
$filter = [];
2018-01-11 15:17:34 -08:00
2019-05-23 17:39:50 -07:00
if ( $request -> filled ( 'filter' )) {
2018-04-25 20:25:03 -07:00
$filter = json_decode ( $request -> input ( 'filter' ), true );
2017-03-11 04:26:01 -08:00
}
2017-01-13 11:41:00 -08:00
$all_custom_fields = CustomField :: all (); //used as a 'cache' of custom fields throughout this page load
foreach ( $all_custom_fields as $field ) {
2021-06-10 13:15:52 -07:00
$allowed_columns [] = $field -> db_column_name ();
2017-01-13 11:41:00 -08:00
}
2023-06-21 16:29:44 -07:00
$assets = Asset :: select ( 'assets.*' )
2021-12-10 18:50:34 -08:00
-> with ( 'location' , 'assetstatus' , 'company' , 'defaultLoc' , 'assignedTo' ,
2021-12-10 18:42:56 -08:00
'model.category' , 'model.manufacturer' , 'model.fieldset' , 'supplier' ); //it might be tempting to add 'assetlog' here, but don't. It blows up update-heavy users.
2017-10-18 10:07:35 -07:00
2022-01-28 09:08:48 -08:00
if ( $filter_non_deprecable_assets ) {
2022-01-15 12:01:19 -08:00
$non_deprecable_models = AssetModel :: select ( 'id' ) -> whereNotNull ( 'depreciation_id' ) -> get ();
$assets -> InModelList ( $non_deprecable_models -> toArray ());
}
2023-06-29 05:35:41 -07:00
2018-01-11 15:17:34 -08:00
// These are used by the API to query against specific ID numbers.
// They are also used by the individual searches on detail pages like
// locations, etc.
2022-01-28 09:08:48 -08:00
// Search custom fields by column name
foreach ( $all_custom_fields as $field ) {
if ( $request -> filled ( $field -> db_column_name ())) {
$assets -> where ( $field -> db_column_name (), '=' , $request -> input ( $field -> db_column_name ()));
}
}
2023-06-29 05:35:41 -07:00
if (( ! is_null ( $filter )) && ( count ( $filter )) > 0 ) {
$assets -> ByFilter ( $filter );
} elseif ( $request -> filled ( 'search' )) {
$assets -> TextSearch ( $request -> input ( 'search' ));
}
2017-01-11 18:14:06 -08:00
2019-05-05 19:32:52 -07:00
// This is used by the audit reporting routes
if ( Gate :: allows ( 'audit' , Asset :: class )) {
switch ( $audit ) {
case 'due' :
$assets -> DueOrOverdueForAudit ( $settings );
break ;
case 'overdue' :
$assets -> overdueForAudit ( $settings );
break ;
}
}
2017-05-15 20:55:39 -07:00
// This is used by the sidenav, mostly
2017-10-17 12:48:18 -07:00
// We switched from using query scopes here because of a Laravel bug
// related to fulltext searches on complex queries.
// I am sad. :(
2017-02-08 03:37:44 -08:00
switch ( $request -> input ( 'status' )) {
2017-01-11 18:14:06 -08:00
case 'Deleted' :
2019-01-24 14:47:44 -08:00
$assets -> onlyTrashed ();
2017-01-11 18:14:06 -08:00
break ;
case 'Pending' :
2021-06-10 13:15:52 -07:00
$assets -> join ( 'status_labels AS status_alias' , function ( $join ) {
$join -> on ( 'status_alias.id' , '=' , 'assets.status_id' )
-> where ( 'status_alias.deployable' , '=' , 0 )
-> where ( 'status_alias.pending' , '=' , 1 )
2017-10-18 01:21:08 -07:00
-> where ( 'status_alias.archived' , '=' , 0 );
2017-10-17 12:48:18 -07:00
});
2017-01-11 18:14:06 -08:00
break ;
case 'RTD' :
2017-10-18 01:21:08 -07:00
$assets -> whereNull ( 'assets.assigned_to' )
2021-06-10 13:15:52 -07:00
-> join ( 'status_labels AS status_alias' , function ( $join ) {
$join -> on ( 'status_alias.id' , '=' , 'assets.status_id' )
-> where ( 'status_alias.deployable' , '=' , 1 )
-> where ( 'status_alias.pending' , '=' , 0 )
2019-02-13 04:45:21 -08:00
-> where ( 'status_alias.archived' , '=' , 0 );
});
2017-01-11 18:14:06 -08:00
break ;
case 'Undeployable' :
$assets -> Undeployable ();
break ;
case 'Archived' :
2021-06-10 13:15:52 -07:00
$assets -> join ( 'status_labels AS status_alias' , function ( $join ) {
$join -> on ( 'status_alias.id' , '=' , 'assets.status_id' )
-> where ( 'status_alias.deployable' , '=' , 0 )
-> where ( 'status_alias.pending' , '=' , 0 )
2017-10-18 01:21:08 -07:00
-> where ( 'status_alias.archived' , '=' , 1 );
2017-10-17 12:48:18 -07:00
});
2017-01-11 18:14:06 -08:00
break ;
case 'Requestable' :
2017-10-17 12:48:18 -07:00
$assets -> where ( 'assets.requestable' , '=' , 1 )
2021-06-10 13:15:52 -07:00
-> join ( 'status_labels AS status_alias' , function ( $join ) {
$join -> on ( 'status_alias.id' , '=' , 'assets.status_id' )
-> where ( 'status_alias.deployable' , '=' , 1 )
-> where ( 'status_alias.pending' , '=' , 0 )
2019-02-13 04:45:21 -08:00
-> where ( 'status_alias.archived' , '=' , 0 );
});
2017-10-17 12:48:18 -07:00
2017-01-11 18:14:06 -08:00
break ;
case 'Deployed' :
2017-10-17 12:48:18 -07:00
// more sad, horrible workarounds for laravel bugs when doing full text searches
2023-06-29 05:35:41 -07:00
$assets -> whereNotNull ( 'assets.assigned_to' );
2017-01-11 18:14:06 -08:00
break ;
2023-01-18 13:25:46 -08:00
case 'byod' :
// This is kind of redundant, since we already check for byod=1 above, but this keeps the
// sidebar nav links a little less chaotic
$assets -> where ( 'assets.byod' , '=' , '1' );
break ;
2017-10-17 11:20:05 -07:00
default :
2018-01-17 19:18:48 -08:00
2021-06-10 13:15:52 -07:00
if (( ! $request -> filled ( 'status_id' )) && ( $settings -> show_archived_in_list != '1' )) {
2018-01-17 19:18:48 -08:00
// terrible workaround for complex-query Laravel bug in fulltext
2021-06-10 13:15:52 -07:00
$assets -> join ( 'status_labels AS status_alias' , function ( $join ) {
$join -> on ( 'status_alias.id' , '=' , 'assets.status_id' )
2018-01-17 19:18:48 -08:00
-> where ( 'status_alias.archived' , '=' , 0 );
});
2019-02-13 04:45:21 -08:00
// If there is a status ID, don't take show_archived_in_list into consideration
2018-02-01 14:31:32 -08:00
} else {
2021-06-10 13:15:52 -07:00
$assets -> join ( 'status_labels AS status_alias' , function ( $join ) {
$join -> on ( 'status_alias.id' , '=' , 'assets.status_id' );
2018-02-01 14:31:32 -08:00
});
2018-01-17 19:18:48 -08:00
}
2017-01-11 18:14:06 -08:00
}
2018-04-25 20:25:03 -07:00
2023-06-21 01:26:54 -07:00
// Leave these under the TextSearch scope, else the fuzziness will override the specific ID (status ID, etc) requested
2023-06-21 01:24:17 -07:00
if ( $request -> filled ( 'status_id' )) {
$assets -> where ( 'assets.status_id' , '=' , $request -> input ( 'status_id' ));
}
if ( $request -> filled ( 'asset_tag' )) {
$assets -> where ( 'assets.asset_tag' , '=' , $request -> input ( 'asset_tag' ));
}
if ( $request -> filled ( 'serial' )) {
$assets -> where ( 'assets.serial' , '=' , $request -> input ( 'serial' ));
}
if ( $request -> input ( 'requestable' ) == 'true' ) {
$assets -> where ( 'assets.requestable' , '=' , '1' );
}
if ( $request -> filled ( 'model_id' )) {
$assets -> InModelList ([ $request -> input ( 'model_id' )]);
}
if ( $request -> filled ( 'category_id' )) {
$assets -> InCategory ( $request -> input ( 'category_id' ));
}
if ( $request -> filled ( 'location_id' )) {
$assets -> where ( 'assets.location_id' , '=' , $request -> input ( 'location_id' ));
}
if ( $request -> filled ( 'rtd_location_id' )) {
$assets -> where ( 'assets.rtd_location_id' , '=' , $request -> input ( 'rtd_location_id' ));
}
if ( $request -> filled ( 'supplier_id' )) {
$assets -> where ( 'assets.supplier_id' , '=' , $request -> input ( 'supplier_id' ));
}
if ( $request -> filled ( 'asset_eol_date' )) {
$assets -> where ( 'assets.asset_eol_date' , '=' , $request -> input ( 'asset_eol_date' ));
}
if (( $request -> filled ( 'assigned_to' )) && ( $request -> filled ( 'assigned_type' ))) {
$assets -> where ( 'assets.assigned_to' , '=' , $request -> input ( 'assigned_to' ))
-> where ( 'assets.assigned_type' , '=' , $request -> input ( 'assigned_type' ));
}
if ( $request -> filled ( 'company_id' )) {
$assets -> where ( 'assets.company_id' , '=' , $request -> input ( 'company_id' ));
}
if ( $request -> filled ( 'manufacturer_id' )) {
$assets -> ByManufacturer ( $request -> input ( 'manufacturer_id' ));
}
if ( $request -> filled ( 'depreciation_id' )) {
$assets -> ByDepreciationId ( $request -> input ( 'depreciation_id' ));
}
if ( $request -> filled ( 'byod' )) {
$assets -> where ( 'assets.byod' , '=' , $request -> input ( 'byod' ));
}
2017-01-11 18:14:06 -08:00
2023-06-22 13:16:24 -07:00
if ( $request -> filled ( 'order_number' )) {
2023-10-18 06:36:16 -07:00
$assets -> where ( 'assets.order_number' , '=' , strval ( $request -> get ( 'order_number' )));
2023-06-22 13:16:24 -07:00
}
2017-01-11 18:14:06 -08:00
2017-10-18 09:27:34 -07:00
// This is kinda gross, but we need to do this because the Bootstrap Tables
// API passes custom field ordering as custom_fields.fieldname, and we have to strip
// that out to let the default sorter below order them correctly on the assets table.
2021-06-10 13:15:52 -07:00
$sort_override = str_replace ( 'custom_fields.' , '' , $request -> input ( 'sort' ));
2017-10-18 09:27:34 -07:00
// This handles all of the pivot sorting (versus the assets.* fields
// in the allowed_columns array)
$column_sort = in_array ( $sort_override , $allowed_columns ) ? $sort_override : 'assets.created_at' ;
2019-02-13 04:45:21 -08:00
2023-06-29 05:35:41 -07:00
$order = $request -> input ( 'order' ) === 'asc' ? 'asc' : 'desc' ;
2017-10-18 09:27:34 -07:00
switch ( $sort_override ) {
2017-01-11 18:14:06 -08:00
case 'model' :
2017-01-13 11:41:00 -08:00
$assets -> OrderModels ( $order );
2017-01-11 18:14:06 -08:00
break ;
case 'model_number' :
2017-01-13 11:41:00 -08:00
$assets -> OrderModelNumber ( $order );
2017-01-11 18:14:06 -08:00
break ;
case 'category' :
2017-01-13 11:41:00 -08:00
$assets -> OrderCategory ( $order );
2017-01-11 18:14:06 -08:00
break ;
case 'manufacturer' :
2017-01-13 11:41:00 -08:00
$assets -> OrderManufacturer ( $order );
2017-01-11 18:14:06 -08:00
break ;
2017-01-13 11:41:00 -08:00
case 'company' :
$assets -> OrderCompany ( $order );
2017-01-11 18:14:06 -08:00
break ;
case 'location' :
2017-01-13 11:41:00 -08:00
$assets -> OrderLocation ( $order );
2018-01-24 14:27:12 -08:00
case 'rtd_location' :
$assets -> OrderRtdLocation ( $order );
2017-01-11 18:14:06 -08:00
break ;
case 'status_label' :
2017-01-13 11:41:00 -08:00
$assets -> OrderStatus ( $order );
2017-01-11 18:14:06 -08:00
break ;
2017-05-15 20:55:39 -07:00
case 'supplier' :
$assets -> OrderSupplier ( $order );
break ;
2017-01-11 18:14:06 -08:00
case 'assigned_to' :
2017-01-13 11:41:00 -08:00
$assets -> OrderAssigned ( $order );
2017-01-11 18:14:06 -08:00
break ;
default :
2017-05-15 20:55:39 -07:00
$assets -> orderBy ( $column_sort , $order );
2017-01-11 18:14:06 -08:00
break ;
}
2018-01-10 05:44:11 -08:00
2019-02-13 04:44:19 -08:00
2023-06-29 05:35:41 -07:00
// Make sure the offset and limit are actually integers and do not exceed system limits
2023-10-14 12:39:52 -07:00
$offset = ( $request -> input ( 'offset' ) > $assets -> count ()) ? $assets -> count () : app ( 'api_offset_value' );
2023-06-29 05:35:41 -07:00
$limit = app ( 'api_limit_value' );
2017-01-13 11:41:00 -08:00
$total = $assets -> count ();
$assets = $assets -> skip ( $offset ) -> take ( $limit ) -> get ();
2021-09-23 17:23:53 -07:00
2021-10-20 17:26:41 -07:00
2021-09-23 17:23:53 -07:00
/**
* Include additional associated relationships
*/
if ( $request -> input ( 'components' )) {
2021-09-23 17:31:19 -07:00
$assets -> loadMissing ([ 'components' => function ( $query ) {
2021-09-23 17:23:53 -07:00
$query -> orderBy ( 'created_at' , 'desc' );
}]);
}
2021-09-01 17:33:39 -07:00
/**
* Here we ' re just determining which Transformer ( via $transformer ) to use based on the
* variables we set earlier on in this method - we default to AssetsTransformer .
*/
2021-09-23 17:23:53 -07:00
return ( new $transformer ) -> transformAssets ( $assets , $total , $request );
2017-01-11 18:14:06 -08:00
}
2018-03-23 14:50:11 -07:00
/**
* Returns JSON with information about an asset ( by tag ) for detail view .
*
* @ param string $tag
* @ since [ v4 . 2.1 ]
2022-11-15 09:33:56 -08:00
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ return \Illuminate\Http\JsonResponse
2018-03-23 14:50:11 -07:00
*/
2021-09-23 17:23:53 -07:00
public function showByTag ( Request $request , $tag )
2018-03-23 14:50:11 -07:00
{
2022-11-15 09:18:09 -08:00
$this -> authorize ( 'index' , Asset :: class );
2022-11-15 09:33:56 -08:00
$assets = Asset :: where ( 'asset_tag' , $tag ) -> with ( 'assetstatus' ) -> with ( 'assignedTo' );
2018-03-23 14:50:11 -07:00
2022-11-15 09:33:56 -08:00
// Check if they've passed ?deleted=true
if ( $request -> input ( 'deleted' , 'false' ) == 'true' ) {
2022-11-15 09:18:09 -08:00
$assets = $assets -> withTrashed ();
}
2023-01-09 20:23:05 -08:00
if (( $assets = $assets -> get ()) && ( $assets -> count ()) > 0 ) {
2023-01-09 20:40:12 -08:00
// If there is exactly one result and the deleted parameter is not passed, we should pull the first (and only)
// asset from the returned collection, since transformAsset() expects an Asset object, NOT a collection
if (( $assets -> count () == 1 ) && ( $request -> input ( 'deleted' ) != 'true' )) {
2023-01-09 20:23:05 -08:00
return ( new AssetsTransformer ) -> transformAsset ( $assets -> first ());
2022-11-15 09:18:09 -08:00
2023-01-09 20:40:12 -08:00
// If there is more than one result OR if the endpoint is requesting deleted items (even if there is only one
// match, return the normal collection transformed.
} else {
2023-01-09 20:23:05 -08:00
return ( new AssetsTransformer ) -> transformAssets ( $assets , $assets -> count ());
}
2023-01-09 19:54:21 -08:00
2022-11-15 09:18:09 -08:00
}
2023-01-09 20:43:57 -08:00
// If there are 0 results, return the "no such asset" response
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , null , trans ( 'admin/hardware/message.does_not_exist' )), 200 );
2018-03-23 14:50:11 -07:00
}
/**
* Returns JSON with information about an asset ( by serial ) for detail view .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ param string $serial
* @ since [ v4 . 2.1 ]
2022-11-15 09:47:21 -08:00
* @ return \Illuminate\Http\JsonResponse
2018-03-23 14:50:11 -07:00
*/
2021-09-23 17:23:53 -07:00
public function showBySerial ( Request $request , $serial )
2018-03-23 14:50:11 -07:00
{
2019-02-13 04:46:19 -08:00
$this -> authorize ( 'index' , Asset :: class );
2022-11-15 09:33:56 -08:00
$assets = Asset :: where ( 'serial' , $serial ) -> with ( 'assetstatus' ) -> with ( 'assignedTo' );
2018-03-23 14:50:11 -07:00
2022-11-15 09:33:56 -08:00
// Check if they've passed ?deleted=true
if ( $request -> input ( 'deleted' , 'false' ) == 'true' ) {
2021-09-28 04:53:59 -07:00
$assets = $assets -> withTrashed ();
2022-11-15 09:18:09 -08:00
}
2023-01-09 21:05:51 -08:00
2023-01-09 20:23:05 -08:00
if (( $assets = $assets -> get ()) && ( $assets -> count ()) > 0 ) {
2023-01-09 21:05:51 -08:00
return ( new AssetsTransformer ) -> transformAssets ( $assets , $assets -> count ());
2021-09-28 04:53:59 -07:00
}
2023-01-09 19:57:47 -08:00
// If there are 0 results, return the "no such asset" response
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , null , trans ( 'admin/hardware/message.does_not_exist' )), 200 );
2018-03-23 14:50:11 -07:00
}
2019-02-13 04:45:21 -08:00
/**
2017-01-11 19:00:34 -08:00
* Returns JSON with information about an asset for detail view .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ param int $assetId
2017-01-11 23:40:56 -08:00
* @ since [ v4 . 0 ]
2023-10-25 08:40:49 -07:00
* @ return \Illuminate\Http\JsonResponse
2017-01-11 19:00:34 -08:00
*/
2021-09-23 17:23:53 -07:00
public function show ( Request $request , $id )
2017-01-11 19:00:34 -08:00
{
2018-07-24 22:40:05 -07:00
if ( $asset = Asset :: with ( 'assetstatus' ) -> with ( 'assignedTo' ) -> withTrashed ()
-> withCount ( 'checkins as checkins_count' , 'checkouts as checkouts_count' , 'userRequests as user_requests_count' ) -> findOrFail ( $id )) {
2017-01-11 19:00:34 -08:00
$this -> authorize ( 'view' , $asset );
2021-06-10 13:15:52 -07:00
2021-09-23 17:23:53 -07:00
return ( new AssetsTransformer ) -> transformAsset ( $asset , $request -> input ( 'components' ) );
2017-01-11 19:00:34 -08:00
}
2018-03-23 14:50:11 -07:00
2017-01-11 19:00:34 -08:00
}
2021-06-10 13:15:52 -07:00
2021-09-23 17:23:53 -07:00
public function licenses ( Request $request , $id )
2019-01-22 14:47:40 -08:00
{
$this -> authorize ( 'view' , Asset :: class );
$this -> authorize ( 'view' , License :: class );
2023-03-29 18:11:28 -07:00
$asset = Asset :: where ( 'id' , $id ) -> withTrashed () -> firstorfail ();
2019-01-22 14:47:40 -08:00
$licenses = $asset -> licenses () -> get ();
2019-02-13 04:44:19 -08:00
2019-01-22 14:47:40 -08:00
return ( new LicensesTransformer ()) -> transformLicenses ( $licenses , $licenses -> count ());
}
2019-02-13 04:44:19 -08:00
2017-10-26 21:50:01 -07:00
2017-10-26 02:28:17 -07:00
/**
2017-10-26 21:50:01 -07:00
* Gets a paginated collection for the select2 menus
2017-10-26 02:28:17 -07:00
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
2017-10-26 21:50:01 -07:00
* @ since [ v4 . 0.16 ]
* @ see \App\Http\Transformers\SelectlistTransformer
2023-10-25 08:40:49 -07:00
* @ return \Illuminate\Http\JsonResponse
2017-10-26 02:28:17 -07:00
*/
public function selectlist ( Request $request )
{
2023-06-21 17:21:36 -07:00
$assets = Asset :: select ([
2017-10-26 02:28:17 -07:00
'assets.id' ,
'assets.name' ,
'assets.asset_tag' ,
'assets.model_id' ,
2017-11-16 16:49:16 -08:00
'assets.assigned_to' ,
'assets.assigned_type' ,
2021-06-10 13:15:52 -07:00
'assets.status_id' ,
2023-06-21 17:21:36 -07:00
]) -> with ( 'model' , 'assetstatus' , 'assignedTo' ) -> NotArchived ();
2017-10-26 02:28:17 -07:00
2019-05-23 17:39:50 -07:00
if ( $request -> filled ( 'assetStatusType' ) && $request -> input ( 'assetStatusType' ) === 'RTD' ) {
2018-04-25 02:39:23 -07:00
$assets = $assets -> RTD ();
}
2017-10-26 02:28:17 -07:00
2019-05-23 17:39:50 -07:00
if ( $request -> filled ( 'search' )) {
2017-11-16 16:49:16 -08:00
$assets = $assets -> AssignedSearch ( $request -> input ( 'search' ));
2017-10-26 02:28:17 -07:00
}
2017-11-16 16:49:16 -08:00
2017-10-26 02:28:17 -07:00
$assets = $assets -> paginate ( 50 );
2017-10-26 21:50:01 -07:00
// Loop through and set some custom properties for the transformer to use.
// This lets us have more flexibility in special cases like assets, where
// they may not have a ->name value but we want to display something anyway
2017-10-26 02:28:17 -07:00
foreach ( $assets as $asset ) {
2017-11-16 16:49:16 -08:00
2017-10-26 21:50:01 -07:00
$asset -> use_text = $asset -> present () -> fullName ;
2017-11-16 16:49:16 -08:00
2017-11-22 15:07:34 -08:00
if (( $asset -> checkedOutToUser ()) && ( $asset -> assigned )) {
2017-11-16 16:49:16 -08:00
$asset -> use_text .= ' → ' . $asset -> assigned -> getFullNameAttribute ();
}
2019-02-13 04:45:21 -08:00
2021-06-10 13:15:52 -07:00
if ( $asset -> assetstatus -> getStatuslabelType () == 'pending' ) {
$asset -> use_text .= '(' . $asset -> assetstatus -> getStatuslabelType () . ')' ;
2017-11-03 11:33:36 -07:00
}
2017-10-26 21:50:01 -07:00
$asset -> use_image = ( $asset -> getImageUrl ()) ? $asset -> getImageUrl () : null ;
2017-10-26 02:28:17 -07:00
}
2017-10-26 03:43:28 -07:00
2017-10-26 21:50:01 -07:00
return ( new SelectlistTransformer ) -> transformSelectlist ( $assets );
2017-10-26 02:28:17 -07:00
}
2017-01-11 19:00:34 -08:00
2017-01-11 23:40:56 -08:00
/**
* Accepts a POST request to create a new asset
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
2021-06-29 02:26:24 -07:00
* @ param \App\Http\Requests\ImageUploadRequest $request
2017-01-11 23:40:56 -08:00
* @ since [ v4 . 0 ]
2023-10-25 08:40:49 -07:00
* @ return \Illuminate\Http\JsonResponse
2017-01-11 23:40:56 -08:00
*/
2023-10-31 19:06:44 -07:00
public function store ( StoreAssetRequest $request )
2017-01-11 23:40:56 -08:00
{
2017-08-25 03:26:50 -07:00
$this -> authorize ( 'create' , Asset :: class );
2017-01-11 23:40:56 -08:00
$asset = new Asset ();
2017-03-14 08:37:39 -07:00
$asset -> model () -> associate ( AssetModel :: find (( int ) $request -> get ( 'model_id' )));
2017-01-11 23:40:56 -08:00
$asset -> name = $request -> get ( 'name' );
$asset -> serial = $request -> get ( 'serial' );
$asset -> company_id = Company :: getIdForCurrentUser ( $request -> get ( 'company_id' ));
$asset -> model_id = $request -> get ( 'model_id' );
$asset -> order_number = $request -> get ( 'order_number' );
$asset -> notes = $request -> get ( 'notes' );
2023-07-12 08:39:45 -07:00
$asset -> asset_tag = $request -> get ( 'asset_tag' , Asset :: autoincrement_asset ()); //yup, problem :/
// NO IT IS NOT!!! This is never firing; we SHOW the asset_tag you're going to get, so it *will* be filled in!
2017-01-11 23:40:56 -08:00
$asset -> user_id = Auth :: id ();
$asset -> archived = '0' ;
$asset -> physical = '1' ;
$asset -> depreciate = '0' ;
$asset -> status_id = $request -> get ( 'status_id' , 0 );
$asset -> warranty_months = $request -> get ( 'warranty_months' , null );
2023-04-25 23:39:32 -07:00
$asset -> purchase_cost = $request -> get ( 'purchase_cost' );
$asset -> asset_eol_date = $request -> get ( 'asset_eol_date' , $asset -> present () -> eol_date ());
2017-01-11 23:40:56 -08:00
$asset -> purchase_date = $request -> get ( 'purchase_date' , null );
$asset -> assigned_to = $request -> get ( 'assigned_to' , null );
2022-03-19 16:12:48 -07:00
$asset -> supplier_id = $request -> get ( 'supplier_id' );
2017-01-11 23:40:56 -08:00
$asset -> requestable = $request -> get ( 'requestable' , 0 );
$asset -> rtd_location_id = $request -> get ( 'rtd_location_id' , null );
Squashed commit of the following:
commit e321aeabaed580f8de6ee309b377654620f117be
Merge: 8ec99ff43 37568ae9e
Author: snipe <snipe@snipe.net>
Date: Mon Aug 31 12:14:44 2020 -0700
Merge branch 'master' into integrations/2020-08-31-v5-rc
# Conflicts:
# .all-contributorsrc
# .nvmrc
# README.md
# app/Console/Commands/LdapSync.php
# app/Http/Controllers/Api/ConsumablesController.php
# app/Http/Controllers/Api/ImportController.php
# app/Http/Controllers/Assets/AssetsController.php
# app/Http/Controllers/Auth/LoginController.php
# app/Http/Controllers/CustomFieldsetsController.php
# app/Http/Controllers/LicensesController.php
# app/Http/Controllers/UsersController.php
# app/Importer/import_mappings.md
# app/Models/Ldap.php
# app/Models/Loggable.php
# composer.json
# composer.lock
# config/version.php
# public/css/build/all.css
# public/css/dist/all.css
# public/css/skins/skin-contrast.css
# public/css/skins/skin-contrast.css.map
# public/js/build/all.js
# public/js/build/vue.js
# public/js/build/vue.js.map
# public/js/dist/all.js
# public/mix-manifest.json
# resources/assets/js/components/importer/importer-file.vue
# resources/assets/less/overrides.less
# resources/macros/macros.php
# resources/views/custom_fields/fieldsets/view.blade.php
# resources/views/hardware/edit.blade.php
# resources/views/hardware/labels.blade.php
# resources/views/hardware/view.blade.php
# resources/views/layouts/default.blade.php
# resources/views/modals/model.blade.php
# resources/views/modals/user.blade.php
# resources/views/users/index.blade.php
# routes/api.php
# routes/web/fields.php
# tests/unit/UserTest.php
commit 37568ae9ec021789d910de91bdef5f64e517451a
Merge: 01a832169 32ad9050c
Author: snipe <snipe@snipe.net>
Date: Tue Aug 25 20:49:37 2020 -0700
Merge pull request #8365 from snipe/fixes/8338_google_maps_CSP
Fixed #8338 - Added google maps to CSP
commit 32ad9050cff8a9bfc89e5a832a9bbf1ad03dadd3
Author: snipe <snipe@snipe.net>
Date: Tue Aug 25 20:48:53 2020 -0700
Added google maps to CSP
commit 01a832169c7572960340e743e569fe9ffdc3f996
Merge: bcad49ce7 3c6883489
Author: snipe <snipe@snipe.net>
Date: Tue Aug 25 20:38:31 2020 -0700
Merge pull request #8364 from snipe/fixes/8335_assigned_to_null_on_status_assetlist
Fixed #8335 - added assignedTo scope on status labels API call for assetlist
commit 3c6883489c030df8d90e2f18cab3ad96121205e5
Author: snipe <snipe@snipe.net>
Date: Tue Aug 25 20:37:30 2020 -0700
Added assignedTo scope
commit bcad49ce79ad7aab99bec8b273a78bb531c48ef0
Author: snipe <snipe@snipe.net>
Date: Fri Aug 14 16:10:22 2020 -0700
Try to better handle slack “too many requests” issue
commit b5acca89d72a43f42fb81a4bf06e8b7c3da0b93b
Author: snipe <snipe@snipe.net>
Date: Fri Aug 14 16:02:15 2020 -0700
Check for admin for slack notifications
commit e52919cf1b17871c6bf294cfb1a9be59f6033289
Merge: 714576be4 29f3a5c48
Author: snipe <snipe@snipe.net>
Date: Fri Aug 14 15:35:15 2020 -0700
Merge pull request #8327 from snipe/features/checkin_license_from_all_users
Checkin license from all users cli tool
commit 29f3a5c48f9b9fc4fcfb19cc6eebb1ce1e0e5a91
Author: snipe <snipe@snipe.net>
Date: Fri Aug 14 15:27:40 2020 -0700
Use more verbose annotation for Auth::user if/else
commit 134e8e6fb9958e71b8fa960de53c041324bd9e1c
Author: snipe <snipe@snipe.net>
Date: Fri Aug 14 15:25:07 2020 -0700
Moved user email nulling until after the save
commit 714576be45dabe9a2b23d3090ec0c72ab8ec28da
Merge: b999c50a2 512899294
Author: Brady Wetherington <bwetherington@grokability.com>
Date: Fri Aug 14 15:24:03 2020 -0700
Merge pull request #8328 from snipe/fix_deprecation_report
Fix deprecation report for customers with many active assets
commit 5128992940b8565e5e87a2a917d3bcde8e21b711
Author: Brady Wetherington <uberbrady@gmail.com>
Date: Fri Aug 14 15:03:03 2020 -0700
Fix deprecation report for customers with many active assets
commit 02913235020d242e959f274fec588d9ebf8e39fa
Author: snipe <snipe@snipe.net>
Date: Fri Aug 14 14:57:58 2020 -0700
Use the user as the target
commit e0f6f9b83972ef9fde79dbc342555580a0574591
Author: snipe <snipe@snipe.net>
Date: Fri Aug 14 14:43:37 2020 -0700
Artisan command to check in licenses from all users
commit f1a6308002caa865fe1a9b17b91d34fbfdd94a75
Author: snipe <snipe@snipe.net>
Date: Fri Aug 14 14:43:07 2020 -0700
Check for Auth::user before trying to log id (for cli)
commit b999c50a2eef14bdf44be8e4359f794194170d2d
Merge: 9ca20e496 e3906b245
Author: snipe <snipe@snipe.net>
Date: Wed Aug 12 12:37:47 2020 -0700
Merge pull request #8316 from Godmartinz/bug/ch15028/missing-or-incorrect-error-message-translation
Looks great, thank you!
commit e3906b245c9b85eca723bffa88b9af28f290e0fe
Author: Godfrey M <godmartinz@gmail.com>
Date: Wed Aug 12 12:27:18 2020 -0700
added translation for admin/licenses/message.not_found
commit 9ca20e4964e57621af8f6b2e790e0d68b69b1afb
Merge: e0644dbbf 456a74d88
Author: Brady Wetherington <bwetherington@grokability.com>
Date: Tue Aug 11 17:33:19 2020 -0700
Merge pull request #8313 from snipe/improve_ldap_search_error_reporting
Improve ldap search error reporting
commit 456a74d88c1b1f14828aaf63e5122eb8b6831755
Author: Brady Wetherington <uberbrady@gmail.com>
Date: Tue Aug 11 16:41:20 2020 -0700
De-merge out incorrectly merged files. Whoops!
commit 799c059070eff849c81550423d16344748522bc7
Author: Brady Wetherington <uberbrady@gmail.com>
Date: Tue Aug 11 16:21:18 2020 -0700
Add internationalized version of LDAP error message
commit c62d43a77831dd798054b95e7ad9e72210f6accf
Author: Brady Wetherington <uberbrady@gmail.com>
Date: Mon Aug 10 17:04:17 2020 -0700
Improve Exception management in Artisan LDAP Sync method. Still need to localize this better
commit b725bd0fae2b062d81a460283aa07b2186a99197
Author: Brady Wetherington <uberbrady@gmail.com>
Date: Mon Aug 10 17:23:04 2020 -0700
Add @PeterUpfold as a contributor
commit e0644dbbf6b5601b6712ca16877b481799e9652c
Merge: 5b6925b00 004ecad05
Author: Brady Wetherington <bwetherington@grokability.com>
Date: Mon Aug 10 17:22:31 2020 -0700
Merge pull request #8105 from PeterUpfold/PeterUpfold-7661workaround
Propose workaround for #7661 — suppress E_DEPRECATED on ldap_control_paged_result()
commit 5b6925b00c04b1abdea0235d04dda32c89215201
Author: snipe <snipe@snipe.net>
Date: Tue Aug 4 21:00:37 2020 -0700
Removed debugging :(
commit df17a859bfab8876d3e849c42692e01bdfdbd886
Author: snipe <snipe@snipe.net>
Date: Tue Aug 4 20:59:54 2020 -0700
Changed modal IDs so manager creation modal works on user creation main page
commit 24c43056ba9e738334eb2310db7c9920d9ab0613
Author: snipe <snipe@snipe.net>
Date: Tue Aug 4 20:58:28 2020 -0700
Moved pGenerator script to default layout footer
This fixes an issue where the password generator wouldn’t load in a modal in Chrome
commit 606b7e905df1918336cef64984e54207ca6a7644
Author: snipe <snipe@snipe.net>
Date: Fri Jul 31 17:02:33 2020 -0700
Small edits to PR template
Slight text changes to ask specifics about versions
commit d73ddad477cb9c675f15fbd54bdb1486bf8f14fc
Author: snipe <snipe@snipe.net>
Date: Fri Jul 31 16:59:26 2020 -0700
Created a PR template
First draft of the PR guidelines template
commit 9a39cf721e82aa25623e41eeb280d7bed3b3c178
Merge: 7410b1683 8994f3e15
Author: snipe <snipe@snipe.net>
Date: Fri Jul 31 12:18:49 2020 -0700
Merge pull request #8258 from ballertv/features/consumable-api
This looks great, thank you!
commit 7410b16835bab1563bf2b7baaddb55377083a3a0
Merge: e955c983a b09e7d19b
Author: Brady Wetherington <bwetherington@grokability.com>
Date: Fri Jul 24 16:22:44 2020 -0700
Merge pull request #8270 from snipe/improve_ad_useraccountcontrol_v4
Add new useraccountcontrol value for valid AD users
commit 8994f3e15e9fef5d1ec9c44764b424fa7edf9448
Author: andres <andresgutierrez535@gmail.com>
Date: Wed Jul 22 19:57:06 2020 -0400
cleanup
commit d23f1a77cac396a3a4962c5993cf1bdbfcf52a29
Author: andres <andresgutierrez535@gmail.com>
Date: Wed Jul 22 18:46:02 2020 -0400
implement checkout API
commit e955c983a3a9bd7793cf9a5f63b6e2c56d53d63f
Merge: 2fa17ac18 eed41e454
Author: snipe <snipe@snipe.net>
Date: Wed Jul 22 13:43:29 2020 -0700
Merge pull request #8250 from snipe/features/adds_addr_city_state_to_importer
Added address, city, state and country to importer and city to bulk editor
commit b09e7d19b3bc424d5960de9f5ffd272b2f19c272
Author: Brady Wetherington <uberbrady@gmail.com>
Date: Wed Jul 22 13:32:16 2020 -0700
Add new useraccountcontrol value for valid AD users; document algorithm and values
commit 2fa17ac18557969f5627953f6d041610207656a6
Merge: b90515437 3b1e46f72
Author: snipe <snipe@snipe.net>
Date: Wed Jul 22 12:06:31 2020 -0700
Merge pull request #8254 from Godmartinz/gmartinez_adds_email_formats
Added firstinitial.lastname, lastname_firstinitial, firstnamelastname…
commit 3b1e46f72b81bd27e5ba0783c88f9d0d0038d611
Author: Godfrey Martinez <47435081+Godmartinz@users.noreply.github.com>
Date: Wed Jul 22 11:25:57 2020 -0700
Update general.php
commit 0c1a1de2a21dfd3639e3d2d2df995c3452c15a11
Author: Godfrey Martinez <47435081+Godmartinz@users.noreply.github.com>
Date: Wed Jul 22 11:24:36 2020 -0700
Update general.php
fixed typo
commit 20c9ae5818ae22846bf2149f261e7f70cc8a7c71
Author: Godfrey M <godmartinz@gmail.com>
Date: Wed Jul 22 10:21:19 2020 -0700
Added firstinitial.lastname, lastname_firstinitial, firstnamelastname and firstnamelastinitial to username formats
commit eed41e454962bb6e9e6cbcf79cb4aed292ac2bbf
Author: snipe <snipe@snipe.net>
Date: Tue Jul 21 16:57:32 2020 -0700
Moved address down further, fixed broken HTML
commit b750f4754f5f4245c0f490f6b6832b4c10615f27
Author: snipe <snipe@snipe.net>
Date: Tue Jul 21 16:49:54 2020 -0700
Added city to bulk user importer
commit c17a06792a76ee11215bd576f2df9732416b3e9d
Author: snipe <snipe@snipe.net>
Date: Tue Jul 21 16:49:38 2020 -0700
Added address, city, state, country to user importer
commit 4f76cc6cfbad1eeded1981e8569e915ca37b87d9
Author: snipe <snipe@snipe.net>
Date: Tue Jul 21 16:46:13 2020 -0700
I don’t actually know what this file is for
commit b905154373bcf0b1ef64d57bb95f184557caba37
Author: snipe <snipe@snipe.net>
Date: Mon Jul 20 14:29:32 2020 -0700
Fixed #8247 - added notes field to user details display
commit daf748e531324215bfd746b406407fee7476d0ab
Author: snipe <snipe@snipe.net>
Date: Fri Jul 17 12:32:01 2020 -0700
Bumped hash
commit 799a93c46a198a8235bbce1527ea7bf4929129c2
Author: snipe <snipe@snipe.net>
Date: Fri Jul 17 12:11:32 2020 -0700
Allow for email/username search on users
commit 34aa12e229fef497b355a492b5ef2c003337786b
Merge: 81a633288 897757bd0
Author: snipe <snipe@snipe.net>
Date: Thu Jul 16 17:44:13 2020 -0700
Merge pull request #8239 from snipe/fixes/api_rtd_to_location_on_create
Set location_id to rtd_location_id on asset creation
commit 897757bd0461cefd2e82aba344d416ed6843c49c
Author: snipe <snipe@snipe.net>
Date: Thu Jul 16 17:43:44 2020 -0700
Removed added line for location
commit c7125c39375b101f852930536dabcc079f2d5e88
Author: snipe <snipe@snipe.net>
Date: Thu Jul 16 16:34:39 2020 -0700
Set location_id to rtd_location_id on asset creation
commit 81a6332889e9e4684ee65a669bc2b3bc1a3ced50
Author: snipe <snipe@snipe.net>
Date: Tue Jul 14 13:55:38 2020 -0700
Removed license ID from seats table cookie info
This typically wouldn’t be necessary, since most people would want to view the same *types* of data across licenses
commit 6e563f6e4bfd9f8b52c8c8d39a60b466e64ba654
Merge: 5320f5c67 7f69ae953
Author: snipe <snipe@snipe.net>
Date: Mon Jul 13 21:16:54 2020 -0700
Merge branch 'master' of https://github.com/snipe/snipe-it
commit 5320f5c67ce7dbf4605cc5b7fd7be8773c8ee157
Author: snipe <snipe@snipe.net>
Date: Mon Jul 13 21:16:45 2020 -0700
Disallow non-super users from editing their own permissions
commit 7f69ae953b7990107bd0db3de16621e5238136e9
Merge: c79f8c1ba 17f6fbabf
Author: snipe <snipe@snipe.net>
Date: Mon Jul 13 21:16:00 2020 -0700
Merge pull request #8227 from snipe/fix_select2_ajax_pulldowns
Changes how we do AJAX calls via Select2 for dynamic drop-down menus
commit 17f6fbabfaa15f203a6accecf6a7b83c35d56ef8
Author: Brady Wetherington <uberbrady@gmail.com>
Date: Mon Jul 13 21:12:03 2020 -0700
Switch to 'items' to maintain compatbility with other internal API's
commit c79f8c1baf920f41d43827094691275eec529448
Merge: 12c92e30b 536401fe0
Author: snipe <snipe@snipe.net>
Date: Mon Jul 13 17:42:16 2020 -0700
Merge pull request #8207 from EDVLeer/patch-1
Update snipeit.sh
commit e7a820f7c91c14280f96e0e58f9921f73cf88c43
Author: Brady Wetherington <uberbrady@gmail.com>
Date: Mon Jul 13 17:14:31 2020 -0700
Changes how we do AJAX calls via Select2 for dynamic drop-down menus
commit 12c92e30b7a20ecd0e45b5a052b43c81dd35cc97
Author: snipe <snipe@snipe.net>
Date: Fri Jul 10 16:21:27 2020 -0700
Show whether or not the user was imported via LDAP in the view page
commit fd10b755b0241e354a265454c13965228a265a85
Author: snipe <snipe@snipe.net>
Date: Fri Jul 10 11:30:01 2020 -0700
Removed the sr-only tag in table headers
It was breaking Bootstrap Tables column selector :(
commit dbbb7680d9d92ab42ffcca825fd93ff6cc3e5f89
Author: snipe <snipe@snipe.net>
Date: Thu Jul 9 21:12:50 2020 -0700
A few more fixes for the cli
Do not check out a piece of software if it’s already been checked out to the user
commit cf0dd5bbadef3689dd9110d96e7d060ddb5fc827
Author: snipe <snipe@snipe.net>
Date: Thu Jul 9 20:43:13 2020 -0700
Small fixes for cli tool
commit 25e53d8c7f4ba1d5977bb5fbc5265ac9c8c543d9
Merge: ec6ed256f 89d433b41
Author: snipe <snipe@snipe.net>
Date: Thu Jul 9 20:27:01 2020 -0700
Merge pull request #8216 from snipe/features/checkout_license_to_all_users
Added CLI tool to checkout license to all users
commit 89d433b41aa0de862cb60142c8d6ef80f339a958
Author: snipe <snipe@snipe.net>
Date: Thu Jul 9 20:26:02 2020 -0700
Removed duplicate seat call
commit e2570ada6f158dfc9acead583a0b2fa7fae17ca6
Author: snipe <snipe@snipe.net>
Date: Thu Jul 9 20:04:05 2020 -0700
CLI tool to checkout a license to ALL users
commit 45afe725a1f039dddd87537e16470963684f0711
Author: snipe <snipe@snipe.net>
Date: Thu Jul 9 20:03:47 2020 -0700
Only try to get the company if there is an auth’d user
(Needed for command line tools, where no Auth::user() is present)
commit 536401fe0ff97cd6a8077cef993bfe755ed46851
Author: EDVLeer <32170051+EDVLeer@users.noreply.github.com>
Date: Tue Jul 7 08:21:36 2020 +0200
Update snipeit.sh
Ubuntu 20.04
commit ec6ed256fbc7740f76ee22867b6fe2008ff7873e
Author: snipe <snipe@snipe.net>
Date: Mon Jul 6 18:45:43 2020 -0700
Bumped minor version
commit 2aaa7bed2d4fad6e8f7b101ecdae1f46ab8a00c2
Merge: 339bdddc3 cc9f1577a
Author: snipe <snipe@snipe.net>
Date: Thu Jun 25 18:37:41 2020 -0700
Merge pull request #8183 from snipe/features/merge_users
Added merge utility
commit cc9f1577a47708a6e11dffeab4797982be243cfa
Author: snipe <snipe@snipe.net>
Date: Thu Jun 25 17:43:53 2020 -0700
Removed unused use directives
commit ab1fe8be0c72522273c468dfd5551553d9f92665
Author: snipe <snipe@snipe.net>
Date: Thu Jun 25 17:42:39 2020 -0700
Added merge utility
commit 339bdddc384aa655fa186dc36e02cc587487d4af
Author: snipe <snipe@snipe.net>
Date: Thu Jun 25 11:00:33 2020 -0700
Fix for Vue js not loading due to CSP :(
commit 35b9cf4b703b9ced785daec1d35973ca266cdc49
Author: snipe <snipe@snipe.net>
Date: Tue Jun 23 02:41:59 2020 -0700
Fixed missing db prefix on scopeDueOrOverdueForAudit
commit 7ccb41371e0efc46d51abc790f49a9fb73e9b8bc
Author: snipe <snipe@snipe.net>
Date: Tue Jun 23 01:09:39 2020 -0700
Removed unoptimized images directive
securityheaders.com is claiming it’s onrecognized, even though I got that directive from their site, so… whatever. ¯\_(ツ)_/¯
commit 2e60a457bf45640a0563a2bc4b66e02b0d226271
Author: snipe <snipe@snipe.net>
Date: Tue Jun 23 01:07:00 2020 -0700
Dumb fix for feature-policy being dumb.
commit 2390d2160bff7b4b340696fa527b1bc871bddff1
Merge: b42801f6a 00b051b8c
Author: snipe <snipe@snipe.net>
Date: Tue Jun 23 00:27:47 2020 -0700
Merge pull request #8164 from snipe/features/additional_security_headers
Additional security headers
commit 00b051b8c7f1af5218a11f2b33fcab37934bd894
Author: snipe <snipe@snipe.net>
Date: Tue Jun 23 00:26:09 2020 -0700
Added a few more comments
commit 05b3a9ad7e72cc71b09ed8ef2e87db19fa3700ee
Author: snipe <snipe@snipe.net>
Date: Mon Jun 22 23:17:27 2020 -0700
Config variable for HSTS
commit 4fb880384fd455bd59a3b91c4244c392d7198c48
Author: snipe <snipe@snipe.net>
Date: Mon Jun 22 22:37:14 2020 -0700
Changed comment
commit 43042ad8412d8d89a9b09e47e5da8b276c9655f2
Author: snipe <snipe@snipe.net>
Date: Mon Jun 22 22:35:59 2020 -0700
Consolidated ReferrerPolicy into new SecurityHeaders file
commit a716382ac43d0a58b96604a3ec15e389b7ae97c2
Author: snipe <snipe@snipe.net>
Date: Mon Jun 22 22:33:37 2020 -0700
Removed CSP middleware (it’s added in the general header)
commit 36c8f7f4f116666c63ae7bc0d12e15f77a8fd6bc
Author: snipe <snipe@snipe.net>
Date: Mon Jun 22 22:31:01 2020 -0700
Additional security headers
commit b42801f6ae635e843d9e062b4119d86fb3d05fc6
Merge: de4934f21 946129f20
Author: snipe <snipe@snipe.net>
Date: Mon Jun 22 20:47:35 2020 -0700
Merge pull request #8163 from snipe/fixes/fix-for-css-on-column-selector
Fixed weird padlock display in asset listing with encrypted custom fields
commit 946129f20614e65bbbecbbda70cfba81b89d0937
Author: snipe <snipe@snipe.net>
Date: Mon Jun 22 20:45:20 2020 -0700
Made quote style consistent
commit b941ef1e08f84f40f503db6ebe67d0e8dca9c74a
Author: snipe <snipe@snipe.net>
Date: Mon Jun 22 20:41:40 2020 -0700
Pulled CSS font awesome styles out of the blade and into overrides.css
commit d1aa11ec89347fb2c139d751719c4459c2448321
Author: snipe <snipe@snipe.net>
Date: Mon Jun 22 20:29:19 2020 -0700
Fix for weird padlock display in asset listing with encrypted custom fields
commit de4934f21d34a628e57992fc6a59813f42c55d90
Merge: af06e4205 b10076b01
Author: snipe <snipe@snipe.net>
Date: Mon Jun 22 17:28:38 2020 -0700
Merge pull request #8162 from Godmartinz/godfreymartinez-ghi-font-size-of-qr_text
Fixed #8161 and #8114 - font-size for labels used static values in blade instead of using values from settings
commit b10076b015ac0034fded62548135aaff3f1b2a0a
Author: Godfrey M <godmartinz@gmail.com>
Date: Mon Jun 22 17:04:39 2020 -0700
corrected an error where font-size for labels were static in settings.
commit af06e4205627b29f583b2e2e770fd2913fce5e46
Author: snipe <snipe@snipe.net>
Date: Wed Jun 17 11:17:25 2020 -0700
Bumped version
commit 9a2440dc4b98a9c12b38a04504875c7c196a510c
Merge: beae8efb2 2ac1c1636
Author: snipe <snipe@snipe.net>
Date: Tue Jun 16 20:20:07 2020 -0700
Merge pull request #8141 from snipe/fixes/better_handling_when_license_is_invalid
Better handle the logic to determine if we should display the license checkout blade [ch13792]
commit 2ac1c1636c672db59d601bd5c73d4a8023533ec9
Author: snipe <snipe@snipe.net>
Date: Tue Jun 16 16:12:57 2020 -0700
Better handle the logic to determine if we should display the license checkout blade
commit 004ecad059d636cc5be62aa5f112e3c4f9762326
Author: Peter Upfold <pgithub@upfold.org.uk>
Date: Wed Jun 3 08:59:50 2020 +0100
Force suppress deprecation warning on ldap_control_paged_result()
commit beae8efb21c2675b3da4308a87d911c534e70361
Merge: d14ab7e3e 9839e5e56
Author: snipe <snipe@snipe.net>
Date: Wed May 27 23:01:33 2020 -0700
Merge pull request #8088 from Godmartinz/Label_Woes
Barcode resizing and text adjustment
commit 9839e5e566f51f85abe6860dfc8377042834c89b
Author: Godfrey M <godmartinz@gmail.com>
Date: Wed May 27 12:27:40 2020 -0700
adjusted for all label text, removed local variable
commit d14ab7e3e1bf09c931ad148fdb6b65ee5a3dc7b8
Author: snipe <snipe@snipe.net>
Date: Wed May 27 00:22:44 2020 -0700
Porting change from #8053 to master
Signed-off-by: snipe <snipe@snipe.net>
commit e7f74d94c179730f8b8502da5e2c1c90fa8ec594
Author: Godfrey M <godmartinz@gmail.com>
Date: Tue May 26 17:22:45 2020 -0700
Label_Woes
commit e97cf011b65df9e66826c26464fed7bf4001917a
Author: Godfrey M <godmartinz@gmail.com>
Date: Tue May 26 17:15:39 2020 -0700
Label_Woes
commit ed23505054cd1bdf2ef695b6b010e025382f38da
Author: Godfrey M <godmartinz@gmail.com>
Date: Tue May 26 17:10:45 2020 -0700
Label_Woes
commit 001e721530c41fd8ad8e925cecdef2eb8c96ab4c
Merge: f88683766 8210da6e8
Author: snipe <snipe@snipe.net>
Date: Wed May 20 10:21:52 2020 -0700
Merge pull request #8063 from dmeltzer/backport-8092
BACKPORT: Fix Missing Category selection in Asset Model Modal dialog - [ch14635]
commit 8210da6e82018afab07197abe591a7666a56af21
Author: Daniel Meltzer <dmeltzer.devel@gmail.com>
Date: Wed May 20 10:29:27 2020 -0400
Fix Missing Category selection in Asset Model Modal dialog.
A select html tag needs a full closing tag. is not valid. This was causing the select2 js to barf and eat additional information.
commit f88683766b1c7e9636aebe2fc952e6f036d3882c
Author: snipe <snipe@snipe.net>
Date: Thu May 14 00:55:47 2020 -0700
Roll back previous change
Signed-off-by: snipe <snipe@snipe.net>
commit e4385c0f8c584061670a1f98b13bbe90a124ac05
Author: snipe <snipe@snipe.net>
Date: Thu May 14 00:48:30 2020 -0700
Fixes #8051 regression
Signed-off-by: snipe <snipe@snipe.net>
commit 0550fe0ffa4e5569bd7ca28354ca282ca2ef2825
Author: snipe <snipe@snipe.net>
Date: Tue May 12 10:31:54 2020 -0700
Fix for session fixation vulnerability
Signed-off-by: snipe <snipe@snipe.net>
commit 7fb3a9b82c09b3aab65bf2b00f76efc66356155e
Merge: 9a2ed804c ecb1e87fe
Author: snipe <snipe@snipe.net>
Date: Mon May 11 22:41:36 2020 -0700
Merge pull request #8043 from snipe/features/backup-optional-in-import-and-ldap
Added option to disable backup in import
commit ecb1e87fe6e7ab67900936a0f158670cc4c21c56
Author: snipe <snipe@snipe.net>
Date: Mon May 11 20:45:15 2020 -0700
Updated assets
Signed-off-by: snipe <snipe@snipe.net>
commit f43df5f04147ded31cc625ef92f87127993e94b3
Author: snipe <snipe@snipe.net>
Date: Mon May 11 20:44:46 2020 -0700
Fixed form label
Signed-off-by: snipe <snipe@snipe.net>
commit 95cc48e422e54b373d3a88d20d15d7536a323dce
Author: snipe <snipe@snipe.net>
Date: Mon May 11 20:41:10 2020 -0700
Added option to disable backup in import
Signed-off-by: snipe <snipe@snipe.net>
commit 9a2ed804ca9f71a9705da604a2c721ceeb9a5567
Author: snipe <snipe@snipe.net>
Date: Mon May 11 20:28:42 2020 -0700
Fixed mismatched HTML header tags
Signed-off-by: snipe <snipe@snipe.net>
commit d20fad28e5e807c7577d9bd0e5146e5607affa33
Author: snipe <snipe@snipe.net>
Date: Mon May 11 20:28:24 2020 -0700
Use more modern request helper
Signed-off-by: snipe <snipe@snipe.net>
commit ae813ddf75b21c45420016033c667ee35a9fc52b
Author: snipe <snipe@snipe.net>
Date: Mon May 11 18:11:16 2020 -0700
Add @alek13 as a contributor
commit bb42109c0c76b6709f39190ae4a1daa55865d306
Author: snipe <snipe@snipe.net>
Date: Mon May 11 18:10:45 2020 -0700
Added a clarifying comment
Signed-off-by: snipe <snipe@snipe.net>
commit f46ecf8ec0c1723e2e04036357c74644c30d4cb7
Author: snipe <snipe@snipe.net>
Date: Mon May 11 18:07:20 2020 -0700
Updated composer lock
Signed-off-by: snipe <snipe@snipe.net>
commit b9e821c0e65e0745064b42aa6cccf9627c5df3e6
Author: snipe <snipe@snipe.net>
Date: Mon May 11 18:07:14 2020 -0700
Small fix for Group Functional Tests
Signed-off-by: snipe <snipe@snipe.net>
commit 9ee28c7513616018f8ff0b8f5b167469e19070eb
Author: snipe <snipe@snipe.net>
Date: Mon May 11 18:07:02 2020 -0700
Switched to use info instead of danger on undeployable statuses
Signed-off-by: snipe <snipe@snipe.net>
commit 1a8ba06702727b1de870d05df53443270b35b8b7
Merge: 0fd232e70 ee4d69b1c
Author: snipe <snipe@snipe.net>
Date: Mon May 11 17:53:32 2020 -0700
Merge branch 'master' of https://github.com/snipe/snipe-it
commit 0fd232e70d2be9ce845a73745ac98800bcfef9e2
Author: snipe <snipe@snipe.net>
Date: Mon May 11 17:53:24 2020 -0700
Fixed group functional test
(We had changed the minimum to 2 instead of 3)
Signed-off-by: snipe <snipe@snipe.net>
commit ee4d69b1c59c6baf832574da9e9bbbe67248a4bc
Merge: 31c535094 d1ad11194
Author: snipe <snipe@snipe.net>
Date: Mon May 11 17:52:45 2020 -0700
Merge pull request #8041 from alek13/patch-1
use supported package for slack
commit d1ad11194936c51050d2e7a77d01c0daa1dde4fd
Author: Alexander Chibrikin <alek13.me@gmail.com>
Date: Mon May 11 20:31:13 2020 +0300
use supported package for slack
see https://github.com/maknz/slack/issues/94
commit 31c5350941c7330aed01652b0670b61f6660b15b
Author: snipe <snipe@snipe.net>
Date: Fri May 1 01:05:48 2020 -0700
Fixed incorrect route for groups edit
Signed-off-by: snipe <snipe@snipe.net>
commit 7eb70e17e0b4d0f1ed1fe3ed7fbff1728eb077fb
Merge: 5bb4f271a 3dfcb4699
Author: snipe <snipe@snipe.net>
Date: Fri Apr 24 04:50:37 2020 -0700
Merge pull request #7993 from snipe/fixes/7989_column_selector
Fixed #7989 - Converted table heading icons in People to CSS glyphs
commit 3dfcb469910456b3213e00c5cd2f839d25dbf2c7
Author: snipe <snipe@snipe.net>
Date: Fri Apr 24 04:41:08 2020 -0700
Minor formatting changes
Signed-off-by: snipe <snipe@snipe.net>
commit 96eb96f964c40b798d5ceed25eff2bbef4f0bc51
Author: snipe <snipe@snipe.net>
Date: Fri Apr 24 04:27:00 2020 -0700
Removed stray val (typo)
Signed-off-by: snipe <snipe@snipe.net>
commit a2f08bd3baa6fb23633ceb58e5408b125b0f0029
Author: snipe <snipe@snipe.net>
Date: Fri Apr 24 04:08:54 2020 -0700
Added comments
Signed-off-by: snipe <snipe@snipe.net>
commit e009fbe59f39a717a4ad7bea5027d39cb5323225
Author: snipe <snipe@snipe.net>
Date: Fri Apr 24 04:04:53 2020 -0700
Converted table heading icons in People to CSS glyphs
Signed-off-by: snipe <snipe@snipe.net>
commit 5bb4f271aaa42a0c211d25e06a500a76c5a224f4
Author: snipe <snipe@snipe.net>
Date: Fri Apr 24 00:47:19 2020 -0700
Fixed #7987 - allow toggle of required/optional in custom fields/fieldsets
Signed-off-by: snipe <snipe@snipe.net>
2020-08-31 12:17:19 -07:00
$asset -> location_id = $request -> get ( 'rtd_location_id' , null );
2017-01-11 23:40:56 -08:00
2023-04-25 23:39:32 -07:00
2021-07-14 03:09:50 -07:00
/**
* this is here just legacy reasons . Api\AssetController
* used image_source once to allow encoded image uploads .
*/
if ( $request -> has ( 'image_source' )) {
$request -> offsetSet ( 'image' , $request -> offsetGet ( 'image_source' ));
}
2021-06-29 02:26:24 -07:00
$asset = $request -> handleImages ( $asset );
2017-01-11 23:40:56 -08:00
// Update custom fields in the database.
// Validation for these fields is handled through the AssetRequest form request
$model = AssetModel :: find ( $request -> get ( 'model_id' ));
2023-05-01 15:05:03 -07:00
2019-05-24 15:44:54 -07:00
if (( $model ) && ( $model -> fieldset )) {
2017-01-11 23:40:56 -08:00
foreach ( $model -> fieldset -> fields as $field ) {
2021-04-05 20:16:06 -07:00
// Set the field value based on what was sent in the request
2022-06-27 14:17:07 -07:00
$field_val = $request -> input ( $field -> db_column , null );
2021-04-05 20:16:06 -07:00
// If input value is null, use custom field's default value
if ( $field_val == null ) {
2022-06-27 14:17:07 -07:00
\Log :: debug ( 'Field value for ' . $field -> db_column . ' is null' );
2021-04-05 20:16:06 -07:00
$field_val = $field -> defaultValue ( $request -> get ( 'model_id' ));
\Log :: debug ( 'Use the default fieldset value of ' . $field -> defaultValue ( $request -> get ( 'model_id' )));
}
// if the field is set to encrypted, make sure we encrypt the value
if ( $field -> field_encrypted == '1' ) {
\Log :: debug ( 'This model field is encrypted in this fieldset.' );
2019-05-15 19:33:30 -07:00
if ( Gate :: allows ( 'admin' )) {
2021-04-05 20:16:06 -07:00
// If input value is null, use custom field's default value
2021-06-10 13:15:52 -07:00
if (( $field_val == null ) && ( $request -> has ( 'model_id' ) != '' )) {
2021-04-05 20:16:06 -07:00
$field_val = \Crypt :: encrypt ( $field -> defaultValue ( $request -> get ( 'model_id' )));
} else {
2022-06-27 14:17:07 -07:00
$field_val = \Crypt :: encrypt ( $request -> input ( $field -> db_column ));
2021-04-05 20:16:06 -07:00
}
2019-05-15 19:33:30 -07:00
}
}
2021-04-05 20:16:06 -07:00
2022-06-27 14:17:07 -07:00
$asset -> { $field -> db_column } = $field_val ;
2017-01-11 23:40:56 -08:00
}
}
if ( $asset -> save ()) {
2017-03-14 08:37:39 -07:00
if ( $request -> get ( 'assigned_user' )) {
2017-01-11 23:40:56 -08:00
$target = User :: find ( request ( 'assigned_user' ));
2017-03-14 08:37:39 -07:00
} elseif ( $request -> get ( 'assigned_asset' )) {
2017-01-11 23:40:56 -08:00
$target = Asset :: find ( request ( 'assigned_asset' ));
2017-03-14 08:37:39 -07:00
} elseif ( $request -> get ( 'assigned_location' )) {
2017-01-11 23:40:56 -08:00
$target = Location :: find ( request ( 'assigned_location' ));
}
2017-01-12 02:19:55 -08:00
if ( isset ( $target )) {
2017-01-11 23:40:56 -08:00
$asset -> checkOut ( $target , Auth :: user (), date ( 'Y-m-d H:i:s' ), '' , 'Checked out on asset creation' , e ( $request -> get ( 'name' )));
}
2019-03-13 21:00:40 -07:00
if ( $asset -> image ) {
$asset -> image = $asset -> getImageUrl ();
}
2017-08-01 20:01:11 -07:00
return response () -> json ( Helper :: formatStandardApiResponse ( 'success' , $asset , trans ( 'admin/hardware/message.create.success' )));
2017-01-11 23:40:56 -08:00
}
2017-08-25 03:26:50 -07:00
2017-03-14 08:37:39 -07:00
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , null , $asset -> getErrors ()), 200 );
2017-01-11 23:40:56 -08:00
}
2017-01-12 03:48:18 -08:00
/**
* Accepts a POST request to update an asset
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
2021-06-29 02:26:24 -07:00
* @ param \App\Http\Requests\ImageUploadRequest $request
2017-01-12 03:48:18 -08:00
* @ since [ v4 . 0 ]
2023-10-25 08:40:49 -07:00
* @ return \Illuminate\Http\JsonResponse
2017-01-12 03:48:18 -08:00
*/
2021-06-29 02:26:24 -07:00
public function update ( ImageUploadRequest $request , $id )
2017-01-12 03:48:18 -08:00
{
2018-07-12 18:28:02 -07:00
$this -> authorize ( 'update' , Asset :: class );
2017-01-12 03:48:18 -08:00
2019-02-13 04:44:19 -08:00
if ( $asset = Asset :: find ( $id )) {
$asset -> fill ( $request -> all ());
2019-02-12 22:08:38 -08:00
2019-05-23 17:39:50 -07:00
( $request -> filled ( 'model_id' )) ?
2019-02-12 22:08:38 -08:00
$asset -> model () -> associate ( AssetModel :: find ( $request -> get ( 'model_id' ))) : null ;
2018-07-24 22:51:31 -07:00
( $request -> filled ( 'rtd_location_id' )) ?
2017-11-03 19:42:45 -07:00
$asset -> location_id = $request -> get ( 'rtd_location_id' ) : '' ;
2019-05-23 17:39:50 -07:00
( $request -> filled ( 'company_id' )) ?
2017-01-12 03:48:18 -08:00
$asset -> company_id = Company :: getIdForCurrentUser ( $request -> get ( 'company_id' )) : '' ;
2019-05-23 17:39:50 -07:00
( $request -> filled ( 'rtd_location_id' )) ?
2019-02-13 04:44:19 -08:00
$asset -> location_id = $request -> get ( 'rtd_location_id' ) : null ;
2018-01-17 13:12:32 -08:00
2021-07-06 23:33:48 -07:00
/**
* this is here just legacy reasons . Api\AssetController
* used image_source once to allow encoded image uploads .
*/
if ( $request -> has ( 'image_source' )) {
$request -> offsetSet ( 'image' , $request -> offsetGet ( 'image_source' ));
}
2021-06-29 02:26:24 -07:00
$asset = $request -> handleImages ( $asset );
2018-01-17 13:12:32 -08:00
// Update custom fields
if (( $model = AssetModel :: find ( $asset -> model_id )) && ( isset ( $model -> fieldset ))) {
foreach ( $model -> fieldset -> fields as $field ) {
2022-06-27 14:17:07 -07:00
if ( $request -> has ( $field -> db_column )) {
2021-06-10 13:15:52 -07:00
if ( $field -> field_encrypted == '1' ) {
2019-05-20 11:49:18 -07:00
if ( Gate :: allows ( 'admin' )) {
2022-06-27 14:17:07 -07:00
$asset -> { $field -> db_column } = \Crypt :: encrypt ( $request -> input ( $field -> db_column ));
2019-05-20 11:49:18 -07:00
}
} else {
2022-06-27 14:17:07 -07:00
$asset -> { $field -> db_column } = $request -> input ( $field -> db_column );
2019-05-15 19:33:30 -07:00
}
2017-01-12 03:48:18 -08:00
}
}
}
2018-01-17 13:12:32 -08:00
2017-01-12 03:48:18 -08:00
if ( $asset -> save ()) {
2019-05-23 17:39:50 -07:00
if (( $request -> filled ( 'assigned_user' )) && ( $target = User :: find ( $request -> get ( 'assigned_user' )))) {
2018-01-17 13:12:32 -08:00
$location = $target -> location_id ;
2019-05-23 17:39:50 -07:00
} elseif (( $request -> filled ( 'assigned_asset' )) && ( $target = Asset :: find ( $request -> get ( 'assigned_asset' )))) {
2019-02-13 04:45:21 -08:00
$location = $target -> location_id ;
2019-12-04 16:19:25 -08:00
2021-06-10 13:16:56 -07:00
Asset :: where ( 'assigned_type' , \App\Models\Asset :: class ) -> where ( 'assigned_to' , $id )
2019-12-04 16:19:25 -08:00
-> update ([ 'location_id' => $target -> location_id ]);
2019-05-23 17:39:50 -07:00
} elseif (( $request -> filled ( 'assigned_location' )) && ( $target = Location :: find ( $request -> get ( 'assigned_location' )))) {
2017-11-03 19:42:45 -07:00
$location = $target -> id ;
2017-01-12 03:48:18 -08:00
}
if ( isset ( $target )) {
2017-11-03 19:42:45 -07:00
$asset -> checkOut ( $target , Auth :: user (), date ( 'Y-m-d H:i:s' ), '' , 'Checked out on asset update' , e ( $request -> get ( 'name' )), $location );
2017-01-12 03:48:18 -08:00
}
2019-03-13 21:00:40 -07:00
if ( $asset -> image ) {
$asset -> image = $asset -> getImageUrl ();
}
2017-03-14 08:37:39 -07:00
return response () -> json ( Helper :: formatStandardApiResponse ( 'success' , $asset , trans ( 'admin/hardware/message.update.success' )));
2017-01-12 03:48:18 -08:00
}
2021-06-10 13:15:52 -07:00
2017-03-14 08:37:39 -07:00
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , null , $asset -> getErrors ()), 200 );
2017-01-12 03:48:18 -08:00
}
2021-06-10 13:15:52 -07:00
2017-03-14 08:37:39 -07:00
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , null , trans ( 'admin/hardware/message.does_not_exist' )), 200 );
2017-01-12 03:48:18 -08:00
}
2017-01-11 23:40:56 -08:00
/**
* Delete a given asset ( mark as deleted ) .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ param int $assetId
* @ since [ v4 . 0 ]
2023-10-25 08:40:49 -07:00
* @ return \Illuminate\Http\JsonResponse
2017-01-11 23:40:56 -08:00
*/
public function destroy ( $id )
{
2017-08-03 19:49:41 -07:00
$this -> authorize ( 'delete' , Asset :: class );
2017-01-11 23:40:56 -08:00
if ( $asset = Asset :: find ( $id )) {
$this -> authorize ( 'delete' , $asset );
DB :: table ( 'assets' )
-> where ( 'id' , $asset -> id )
2021-06-10 13:15:52 -07:00
-> update ([ 'assigned_to' => null ]);
2017-01-11 23:40:56 -08:00
$asset -> delete ();
2017-03-14 08:37:39 -07:00
return response () -> json ( Helper :: formatStandardApiResponse ( 'success' , null , trans ( 'admin/hardware/message.delete.success' )));
2017-01-11 23:40:56 -08:00
}
2017-03-14 08:37:39 -07:00
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , null , trans ( 'admin/hardware/message.does_not_exist' )), 200 );
2021-08-14 14:06:15 -07:00
}
/**
2021-08-14 14:07:04 -07:00
* Restore a soft - deleted asset .
2021-08-14 14:06:15 -07:00
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ param int $assetId
* @ since [ v5 . 1.18 ]
2023-10-25 08:40:49 -07:00
* @ return \Illuminate\Http\JsonResponse
2021-08-14 14:06:15 -07:00
*/
2022-06-09 17:23:50 -07:00
public function restore ( Request $request , $assetId = null )
2021-08-14 14:06:15 -07:00
{
// Get asset information
$asset = Asset :: withTrashed () -> find ( $assetId );
$this -> authorize ( 'delete' , $asset );
2022-06-09 17:23:50 -07:00
2021-08-14 14:06:15 -07:00
if ( isset ( $asset -> id )) {
2022-06-09 17:23:50 -07:00
if ( $asset -> deleted_at == '' ) {
$message = 'Asset was not deleted. No data was changed.' ;
} else {
$message = trans ( 'admin/hardware/message.restore.success' );
// 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' );
}
2021-08-14 14:06:15 -07:00
2022-06-09 17:23:50 -07:00
return response () -> json ( Helper :: formatStandardApiResponse ( 'success' , ( new AssetsTransformer ) -> transformAsset ( $asset , $request ), $message ));
2021-08-14 14:06:15 -07:00
}
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , null , trans ( 'admin/hardware/message.does_not_exist' )), 200 );
2017-01-11 23:40:56 -08:00
}
2022-06-28 23:11:57 -07:00
/**
* Checkout an asset by its tag .
*
* @ author [ N . Butler ]
* @ param string $tag
* @ since [ v6 . 0.5 ]
2023-10-25 08:40:49 -07:00
* @ return \Illuminate\Http\JsonResponse
2022-06-28 23:11:57 -07:00
*/
public function checkoutByTag ( AssetCheckoutRequest $request , $tag )
{
2022-06-29 00:49:50 -07:00
if ( $asset = Asset :: where ( 'asset_tag' , $tag ) -> first ()) {
2022-06-28 23:11:57 -07:00
return $this -> checkout ( $request , $asset -> id );
}
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , null , 'Asset not found' ), 200 );
}
2017-03-11 14:04:52 -08:00
/**
* Checkout an asset
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ param int $assetId
* @ since [ v4 . 0 ]
2023-10-25 08:40:49 -07:00
* @ return \Illuminate\Http\JsonResponse
2017-03-11 14:04:52 -08:00
*/
2017-11-27 21:17:16 -08:00
public function checkout ( AssetCheckoutRequest $request , $asset_id )
2017-03-14 08:37:39 -07:00
{
2017-03-11 14:04:52 -08:00
$this -> authorize ( 'checkout' , Asset :: class );
$asset = Asset :: findOrFail ( $asset_id );
2021-06-10 13:15:52 -07:00
if ( ! $asset -> availableForCheckout ()) {
2017-03-11 14:04:52 -08:00
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , [ 'asset' => e ( $asset -> asset_tag )], trans ( 'admin/hardware/message.checkout.not_available' )));
}
$this -> authorize ( 'checkout' , $asset );
2017-10-19 15:51:55 -07:00
$error_payload = [];
$error_payload [ 'asset' ] = [
'id' => $asset -> id ,
'asset_tag' => $asset -> asset_tag ,
];
2017-11-27 21:17:58 -08:00
// This item is checked out to a location
2021-06-10 13:15:52 -07:00
if ( request ( 'checkout_to_type' ) == 'location' ) {
2017-11-27 21:17:58 -08:00
$target = Location :: find ( request ( 'assigned_location' ));
$asset -> location_id = ( $target ) ? $target -> id : '' ;
$error_payload [ 'target_id' ] = $request -> input ( 'assigned_location' );
$error_payload [ 'target_type' ] = 'location' ;
2021-06-10 13:15:52 -07:00
} elseif ( request ( 'checkout_to_type' ) == 'asset' ) {
$target = Asset :: where ( 'id' , '!=' , $asset_id ) -> find ( request ( 'assigned_asset' ));
2017-11-27 21:17:58 -08:00
// Override with the asset's location_id if it has one
2020-04-06 15:54:40 -07:00
$asset -> location_id = (( $target ) && ( isset ( $target -> location_id ))) ? $target -> location_id : '' ;
2017-11-27 21:17:58 -08:00
$error_payload [ 'target_id' ] = $request -> input ( 'assigned_asset' );
$error_payload [ 'target_type' ] = 'asset' ;
2021-06-10 13:15:52 -07:00
} elseif ( request ( 'checkout_to_type' ) == 'user' ) {
2017-11-27 21:17:58 -08:00
// Fetch the target and set the asset's new location_id
$target = User :: find ( request ( 'assigned_user' ));
2020-04-06 15:54:40 -07:00
$asset -> location_id = (( $target ) && ( isset ( $target -> location_id ))) ? $target -> location_id : '' ;
2017-11-27 21:17:58 -08:00
$error_payload [ 'target_id' ] = $request -> input ( 'assigned_user' );
$error_payload [ 'target_type' ] = 'user' ;
2017-03-11 14:04:52 -08:00
}
2022-04-15 05:06:35 -07:00
if ( $request -> filled ( 'status_id' )) {
$asset -> status_id = $request -> get ( 'status_id' );
}
2017-11-27 21:17:58 -08:00
2021-06-10 13:15:52 -07:00
if ( ! isset ( $target )) {
2017-11-27 21:17:58 -08:00
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , $error_payload , 'Checkout target for asset ' . e ( $asset -> asset_tag ) . ' is invalid - ' . $error_payload [ 'target_type' ] . ' does not exist.' ));
2017-03-11 14:04:52 -08:00
}
2017-10-28 07:38:36 -07:00
2021-06-10 13:15:52 -07:00
$checkout_at = request ( 'checkout_at' , date ( 'Y-m-d H:i:s' ));
2017-03-11 14:04:52 -08:00
$expected_checkin = request ( 'expected_checkin' , null );
$note = request ( 'note' , null );
2023-02-14 12:19:16 -08:00
// Using `->has` preserves the asset name if the name parameter was not included in request.
2023-02-14 12:08:20 -08:00
$asset_name = request () -> has ( 'name' ) ? request ( 'name' ) : $asset -> name ;
2019-02-13 04:45:21 -08:00
2017-10-28 07:38:36 -07:00
// Set the location ID to the RTD location id if there is one
2020-04-09 14:17:39 -07:00
// Wait, why are we doing this? This overrides the stuff we set further up, which makes no sense.
// TODO: Follow up here. WTF. Commented out for now.
2017-11-27 21:17:58 -08:00
2020-04-09 14:17:39 -07:00
// if ((isset($target->rtd_location_id)) && ($asset->rtd_location_id!='')) {
// $asset->location_id = $target->rtd_location_id;
// }
2017-10-28 07:38:36 -07:00
2017-03-11 14:04:52 -08:00
2017-11-27 21:17:58 -08:00
if ( $asset -> checkOut ( $target , Auth :: user (), $checkout_at , $expected_checkin , $note , $asset_name , $asset -> location_id )) {
2017-03-11 14:04:52 -08:00
return response () -> json ( Helper :: formatStandardApiResponse ( 'success' , [ 'asset' => e ( $asset -> asset_tag )], trans ( 'admin/hardware/message.checkout.success' )));
}
2019-08-22 21:36:47 -07:00
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , [ 'asset' => e ( $asset -> asset_tag )], trans ( 'admin/hardware/message.checkout.error' )));
2017-03-11 14:04:52 -08:00
}
/**
* Checkin an asset
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ param int $assetId
* @ since [ v4 . 0 ]
2023-10-25 08:40:49 -07:00
* @ return \Illuminate\Http\JsonResponse
2017-03-11 14:04:52 -08:00
*/
2017-11-03 19:42:45 -07:00
public function checkin ( Request $request , $asset_id )
2017-03-14 08:37:39 -07:00
{
2017-03-11 14:04:52 -08:00
$this -> authorize ( 'checkin' , Asset :: class );
$asset = Asset :: findOrFail ( $asset_id );
$this -> authorize ( 'checkin' , $asset );
2021-12-19 15:39:57 -08:00
$target = $asset -> assignedTo ;
if ( is_null ( $target )) {
2017-03-11 14:04:52 -08:00
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , [ 'asset' => e ( $asset -> asset_tag )], trans ( 'admin/hardware/message.checkin.already_checked_in' )));
}
$asset -> expected_checkin = null ;
$asset -> last_checkout = null ;
2023-08-21 11:57:33 -07:00
$asset -> last_checkin = now ();
2017-03-11 14:04:52 -08:00
$asset -> assigned_to = null ;
$asset -> assignedTo () -> disassociate ( $asset );
$asset -> accepted = null ;
2019-07-26 12:37:38 -07:00
2022-06-21 10:57:39 -07:00
if ( $request -> has ( 'name' )) {
2019-07-26 12:37:38 -07:00
$asset -> name = $request -> input ( 'name' );
}
2021-12-19 13:53:31 -08:00
2021-06-10 13:15:52 -07:00
$asset -> location_id = $asset -> rtd_location_id ;
2017-11-03 19:42:45 -07:00
2019-05-23 17:39:50 -07:00
if ( $request -> filled ( 'location_id' )) {
2021-06-10 13:15:52 -07:00
$asset -> location_id = $request -> input ( 'location_id' );
2017-11-03 19:42:45 -07:00
}
2019-12-11 11:09:54 -08:00
if ( $request -> has ( 'status_id' )) {
2021-06-10 13:15:52 -07:00
$asset -> status_id = $request -> input ( 'status_id' );
2017-03-11 14:04:52 -08:00
}
2022-07-21 21:45:25 -07:00
$checkin_at = $request -> filled ( 'checkin_at' ) ? $request -> input ( 'checkin_at' ) . ' ' . date ( 'H:i:s' ) : date ( 'Y-m-d H:i:s' );
2023-08-31 20:12:07 -07:00
$originalValues = $asset -> getRawOriginal ();
2017-03-11 14:04:52 -08:00
2023-08-31 20:12:07 -07:00
if (( $request -> filled ( 'checkin_at' )) && ( $request -> get ( 'checkin_at' ) != date ( 'Y-m-d' ))) {
$originalValues [ 'action_date' ] = $checkin_at ;
}
2022-02-04 22:52:30 -08:00
2017-03-11 14:04:52 -08:00
if ( $asset -> save ()) {
2023-08-31 20:12:07 -07:00
event ( new CheckoutableCheckedIn ( $asset , $target , Auth :: user (), $request -> input ( 'note' ), $checkin_at , $originalValues ));
2021-06-08 11:16:13 -07:00
2017-03-11 14:04:52 -08:00
return response () -> json ( Helper :: formatStandardApiResponse ( 'success' , [ 'asset' => e ( $asset -> asset_tag )], trans ( 'admin/hardware/message.checkin.success' )));
}
2021-12-19 15:39:57 -08:00
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , [ 'asset' => e ( $asset -> asset_tag )], trans ( 'admin/hardware/message.checkin.error' )));
2017-03-11 14:04:52 -08:00
}
2017-08-25 10:04:19 -07:00
2021-12-19 13:53:31 -08:00
/**
2021-12-19 16:11:24 -08:00
* Checkin an asset by asset tag
2021-12-19 13:53:31 -08:00
*
2021-12-19 15:39:57 -08:00
* @ author [ A . Janes ] [ < ajanes @ adagiohealth . org > ]
2021-12-19 16:11:24 -08:00
* @ since [ v6 . 0 ]
2023-10-25 08:40:49 -07:00
* @ return \Illuminate\Http\JsonResponse
2021-12-19 13:53:31 -08:00
*/
2022-06-29 16:23:52 -07:00
public function checkinByTag ( Request $request , $tag = null )
2021-12-19 13:53:31 -08:00
{
$this -> authorize ( 'checkin' , Asset :: class );
2022-06-29 16:23:52 -07:00
if ( null == $tag && null !== ( $request -> input ( 'asset_tag' ))) {
$tag = $request -> input ( 'asset_tag' );
}
$asset = Asset :: where ( 'asset_tag' , $tag ) -> first ();
2021-12-19 13:53:31 -08:00
2022-07-21 21:45:25 -07:00
if ( $asset ) {
2021-12-19 15:39:57 -08:00
return $this -> checkin ( $request , $asset -> id );
2021-12-19 13:53:31 -08:00
}
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , [
2022-06-29 16:23:52 -07:00
'asset' => e ( $tag )
], 'Asset with tag ' . e ( $tag ) . ' not found' ));
2017-03-11 14:04:52 -08:00
}
2017-08-25 10:04:19 -07:00
/**
* Mark an asset as audited
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ param int $id
* @ since [ v4 . 0 ]
2023-10-25 08:40:49 -07:00
* @ return \Illuminate\Http\JsonResponse
2017-08-25 10:04:19 -07:00
*/
2021-06-10 13:15:52 -07:00
public function audit ( Request $request )
2017-08-25 10:04:19 -07:00
2021-06-10 13:15:52 -07:00
{
2017-08-29 16:00:22 -07:00
$this -> authorize ( 'audit' , Asset :: class );
2021-06-10 13:15:52 -07:00
$rules = [
2017-08-29 16:00:22 -07:00
'asset_tag' => 'required' ,
2017-08-25 18:40:20 -07:00
'location_id' => 'exists:locations,id|nullable|numeric' ,
2021-06-10 13:15:52 -07:00
'next_audit_date' => 'date|nullable' ,
];
2017-08-25 10:04:19 -07:00
2017-08-29 16:00:22 -07:00
$validator = Validator :: make ( $request -> all (), $rules );
2017-08-25 18:40:20 -07:00
if ( $validator -> fails ()) {
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , null , $validator -> errors () -> all ()));
}
2017-08-25 10:04:19 -07:00
2018-08-01 03:04:29 -07:00
$settings = Setting :: getSettings ();
$dt = Carbon :: now () -> addMonths ( $settings -> audit_interval ) -> toDateString ();
2021-06-10 13:15:52 -07:00
$asset = Asset :: where ( 'asset_tag' , '=' , $request -> input ( 'asset_tag' )) -> first ();
2017-08-25 10:04:19 -07:00
2017-08-29 16:00:22 -07:00
if ( $asset ) {
2017-12-12 03:03:43 -08:00
// We don't want to log this as a normal update, so let's bypass that
$asset -> unsetEventDispatcher ();
2018-08-01 03:04:29 -07:00
$asset -> next_audit_date = $dt ;
if ( $request -> filled ( 'next_audit_date' )) {
$asset -> next_audit_date = $request -> input ( 'next_audit_date' );
}
2018-09-07 05:39:41 -07:00
// Check to see if they checked the box to update the physical location,
// not just note it in the audit notes
2021-06-10 13:15:52 -07:00
if ( $request -> input ( 'update_location' ) == '1' ) {
2018-09-07 05:39:41 -07:00
$asset -> location_id = $request -> input ( 'location_id' );
}
2021-01-26 12:22:59 -08:00
$asset -> last_audit_date = date ( 'Y-m-d H:i:s' );
2017-12-12 03:03:43 -08:00
2017-08-29 16:00:22 -07:00
if ( $asset -> save ()) {
2021-06-10 13:15:52 -07:00
$log = $asset -> logAudit ( request ( 'note' ), request ( 'location_id' ));
2017-08-31 21:30:38 -07:00
return response () -> json ( Helper :: formatStandardApiResponse ( 'success' , [
'asset_tag' => e ( $asset -> asset_tag ),
'note' => e ( $request -> input ( 'note' )),
2021-06-10 13:15:52 -07:00
'next_audit_date' => Helper :: getFormattedDateObject ( $asset -> next_audit_date ),
2017-08-31 21:30:38 -07:00
], trans ( 'admin/hardware/message.audit.success' )));
2017-08-29 16:00:22 -07:00
}
2017-08-25 10:04:19 -07:00
}
2021-11-09 19:39:32 -08:00
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , [ 'asset_tag' => e ( $request -> input ( 'asset_tag' ))], 'Asset with tag ' . e ( $request -> input ( 'asset_tag' )) . ' not found' ));
2018-04-04 17:33:02 -07:00
}
/**
* Returns JSON listing of all requestable assets
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ since [ v4 . 0 ]
2023-10-25 09:26:51 -07:00
* @ return \Illuminate\Http\JsonResponse
2018-04-04 17:33:02 -07:00
*/
public function requestable ( Request $request )
{
2018-07-12 18:28:02 -07:00
$this -> authorize ( 'viewRequestable' , Asset :: class );
2023-10-25 09:26:51 -07:00
$allowed_columns = [
'name' ,
'asset_tag' ,
'serial' ,
'model_number' ,
'image' ,
'purchase_cost' ,
'expected_checkin' ,
];
$all_custom_fields = CustomField :: all (); //used as a 'cache' of custom fields throughout this page load
foreach ( $all_custom_fields as $field ) {
$allowed_columns [] = $field -> db_column_name ();
}
2023-06-22 12:36:43 -07:00
$assets = Asset :: select ( 'assets.*' )
2023-10-25 09:26:51 -07:00
-> with ( 'location' , 'assetstatus' , 'assetlog' , 'company' , 'assignedTo' ,
'model.category' , 'model.manufacturer' , 'model.fieldset' , 'supplier' , 'requests' )
2023-06-22 12:36:43 -07:00
-> requestableAssets ();
2018-04-04 17:33:02 -07:00
2023-10-25 09:26:51 -07:00
2022-01-13 16:32:40 -08:00
if ( $request -> filled ( 'search' )) {
$assets -> TextSearch ( $request -> input ( 'search' ));
}
2018-04-04 17:33:02 -07:00
2023-10-25 09:26:51 -07:00
// Search custom fields by column name
foreach ( $all_custom_fields as $field ) {
if ( $request -> filled ( $field -> db_column_name ())) {
$assets -> where ( $field -> db_column_name (), '=' , $request -> input ( $field -> db_column_name ()));
}
}
$order = $request -> input ( 'order' ) === 'asc' ? 'asc' : 'desc' ;
$sort_override = str_replace ( 'custom_fields.' , '' , $request -> input ( 'sort' ));
// This handles all the pivot sorting (versus the assets.* fields
// in the allowed_columns array)
$column_sort = in_array ( $sort_override , $allowed_columns ) ? $sort_override : 'assets.created_at' ;
2018-04-04 17:33:02 -07:00
switch ( $request -> input ( 'sort' )) {
case 'model' :
$assets -> OrderModels ( $order );
break ;
case 'model_number' :
$assets -> OrderModelNumber ( $order );
break ;
2023-10-25 09:26:51 -07:00
case 'location' :
$assets -> OrderLocation ( $order );
2023-10-26 01:21:27 -07:00
break ;
2018-04-04 17:33:02 -07:00
default :
2023-10-25 09:26:51 -07:00
$assets -> orderBy ( $column_sort , $order );
2018-04-04 17:33:02 -07:00
break ;
}
2023-10-25 09:26:51 -07:00
// Make sure the offset and limit are actually integers and do not exceed system limits
$offset = ( $request -> input ( 'offset' ) > $assets -> count ()) ? $assets -> count () : app ( 'api_offset_value' );
$limit = app ( 'api_limit_value' );
2018-04-04 17:33:02 -07:00
$total = $assets -> count ();
$assets = $assets -> skip ( $offset ) -> take ( $limit ) -> get ();
2021-06-10 13:15:52 -07:00
2018-04-04 17:33:02 -07:00
return ( new AssetsTransformer ) -> transformRequestedAssets ( $assets , $total );
2017-08-25 10:04:19 -07:00
}
2017-01-11 18:14:06 -08:00
}