From 0b56ebf291abd98ab32b51a52e6b6e74fc9317b8 Mon Sep 17 00:00:00 2001 From: snipe Date: Mon, 27 Nov 2017 21:16:25 -0800 Subject: [PATCH 01/13] Fixed radio button selector to provide correct default value in checkout --- resources/views/partials/forms/checkout-selector.blade.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/resources/views/partials/forms/checkout-selector.blade.php b/resources/views/partials/forms/checkout-selector.blade.php index 600470b6fa..c622bda5ca 100644 --- a/resources/views/partials/forms/checkout-selector.blade.php +++ b/resources/views/partials/forms/checkout-selector.blade.php @@ -4,7 +4,7 @@
@if ((isset($user_select)) && ($user_select!='false')) @endif @if ((isset($asset_select)) && ($asset_select!='false')) @@ -17,6 +17,8 @@ {{ trans('general.location') }} @endif + + {!! $errors->first('checkout_to_type', ' :message') !!}
From 31a967e072ab7944343e583309e0a9c3caee7492 Mon Sep 17 00:00:00 2001 From: snipe Date: Mon, 27 Nov 2017 21:16:51 -0800 Subject: [PATCH 02/13] Use general order_number string to mean order number --- resources/views/components/view.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/components/view.blade.php b/resources/views/components/view.blade.php index b7b08232c9..5f59e9d465 100644 --- a/resources/views/components/view.blade.php +++ b/resources/views/components/view.blade.php @@ -96,7 +96,7 @@ @endif @if ($component->order_number) -
{{ trans('admin/components/general.order') }}: +
{{ trans('general.order_number') }}: {{ $component->order_number }}
@endif
From 05996019e526a1cce4bccd94826d554032b2481c Mon Sep 17 00:00:00 2001 From: snipe Date: Mon, 27 Nov 2017 21:17:16 -0800 Subject: [PATCH 03/13] Use asset checkout request in API --- app/Http/Controllers/Api/AssetsController.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/Api/AssetsController.php b/app/Http/Controllers/Api/AssetsController.php index 45e323b9c4..5b464d26cb 100644 --- a/app/Http/Controllers/Api/AssetsController.php +++ b/app/Http/Controllers/Api/AssetsController.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers\Api; use App\Helpers\Helper; use App\Http\Controllers\Controller; use App\Http\Requests\AssetRequest; +use App\Http\Requests\AssetCheckoutRequest; use App\Http\Transformers\AssetsTransformer; use App\Models\Asset; use App\Models\AssetModel; @@ -506,7 +507,7 @@ class AssetsController extends Controller * @since [v4.0] * @return JsonResponse */ - public function checkout(Request $request, $asset_id) + public function checkout(AssetCheckoutRequest $request, $asset_id) { $this->authorize('checkout', Asset::class); $asset = Asset::findOrFail($asset_id); From 305b0d8edbd6a46551919f8eeb4e8a73b64d7dad Mon Sep 17 00:00:00 2001 From: snipe Date: Mon, 27 Nov 2017 21:17:58 -0800 Subject: [PATCH 04/13] Fixed #4522 - properly check for valid target, throw error otherwise --- app/Http/Controllers/Api/AssetsController.php | 50 +++++++++++-------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/app/Http/Controllers/Api/AssetsController.php b/app/Http/Controllers/Api/AssetsController.php index 5b464d26cb..3976d473dd 100644 --- a/app/Http/Controllers/Api/AssetsController.php +++ b/app/Http/Controllers/Api/AssetsController.php @@ -523,27 +523,37 @@ class AssetsController extends Controller 'id' => $asset->id, 'asset_tag' => $asset->asset_tag, ]; - if ($request->has('user_id')) { - $target = User::find($request->input('user_id')); - $location = $target->location_id; - $error_payload['target_id'] = $request->input('user_id'); - $error_payload['target_type'] = User::class; - // Don't let the user check an asset out to itself - } elseif ($request->has('asset_id')) { - $target = Asset::where('id','!=',$asset_id)->find($request->input('asset_id')); - $location = $target->location_id; - $error_payload['target_id'] = $request->input('asset_id'); - $error_payload['target_type'] = Asset::class; - } elseif ($request->has('location_id')) { - $target = Location::find($request->input('location_id')); - $location = $target->id; - $target = Location::find($request->input('location_id')); - $error_payload['target_id'] = $request->input('location_id'); - $error_payload['target_type'] = Location::class; + + + // This item is checked out to a location + if (request('checkout_to_type')=='location') { + $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'; + + } elseif (request('checkout_to_type')=='asset') { + $target = Asset::where('id','!=',$assetId)->find(request('assigned_asset')); + $asset->location_id = $target->rtd_location_id; + // Override with the asset's location_id if it has one + if ($target->location_id!='') { + $asset->location_id = ($target) ? $target->location_id : ''; + } + $error_payload['target_id'] = $request->input('assigned_asset'); + $error_payload['target_type'] = 'asset'; + + } elseif (request('checkout_to_type')=='user') { + // Fetch the target and set the asset's new location_id + $target = User::find(request('assigned_user')); + $asset->location_id = ($target) ? $target->location_id : ''; + $error_payload['target_id'] = $request->input('assigned_user'); + $error_payload['target_type'] = 'user'; } + + if (!isset($target)) { - return response()->json(Helper::formatStandardApiResponse('error', $error_payload, 'No valid checkout target specified for asset '.e($asset->asset_tag).'.')); + 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.')); } @@ -558,11 +568,11 @@ class AssetsController extends Controller $asset->location_id = $target->rtd_location_id; } - $asset->location_id = $location; + - if ($asset->checkOut($target, Auth::user(), $checkout_at, $expected_checkin, $note, $asset_name, $location)) { + if ($asset->checkOut($target, Auth::user(), $checkout_at, $expected_checkin, $note, $asset_name, $asset->location_id)) { return response()->json(Helper::formatStandardApiResponse('success', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkout.success'))); } From 804b49cefb31220ed2d7d9c4aa71aa64d3ff21a8 Mon Sep 17 00:00:00 2001 From: snipe Date: Mon, 27 Nov 2017 21:18:29 -0800 Subject: [PATCH 05/13] Make sure the asset is available for checkout before displaying the checkout screen --- app/Http/Controllers/AssetsController.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/AssetsController.php b/app/Http/Controllers/AssetsController.php index 4562ef39d8..d87980cd22 100755 --- a/app/Http/Controllers/AssetsController.php +++ b/app/Http/Controllers/AssetsController.php @@ -431,8 +431,13 @@ class AssetsController extends Controller $this->authorize('checkout', $asset); + if ($asset->availableForCheckout()) { + return view('hardware/checkout', compact('asset')); + } + return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkout.not_available')); + // Get the dropdown of users and then pass it to the checkout view - return view('hardware/checkout', compact('asset')); + } /** From b6c258bb12aeeb889ae64b0c7ad1b190b0c2646b Mon Sep 17 00:00:00 2001 From: snipe Date: Mon, 27 Nov 2017 21:19:50 -0800 Subject: [PATCH 06/13] Redirect to back on bad checkout --- app/Http/Controllers/AssetsController.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/Http/Controllers/AssetsController.php b/app/Http/Controllers/AssetsController.php index d87980cd22..4e020e52e0 100755 --- a/app/Http/Controllers/AssetsController.php +++ b/app/Http/Controllers/AssetsController.php @@ -459,11 +459,13 @@ class AssetsController extends Controller } $this->authorize('checkout', $asset); $admin = Auth::user(); - + + // This item is checked out to a location if (request('checkout_to_type')=='location') { $target = Location::find(request('assigned_location')); $asset->location_id = ($target) ? $target->id : ''; + } elseif (request('checkout_to_type')=='asset') { $target = Asset::where('id','!=',$assetId)->find(request('assigned_asset')); $asset->location_id = $target->rtd_location_id; @@ -471,16 +473,16 @@ class AssetsController extends Controller if ($target->location_id!='') { $asset->location_id = ($target) ? $target->location_id : ''; } - } else { + + } elseif (request('checkout_to_type')=='user') { // Fetch the target and set the asset's new location_id $target = User::find(request('assigned_user')); $asset->location_id = ($target) ? $target->location_id : ''; } - // No valid target was found - error out if (!$target) { - return redirect()->to("hardware/$assetId/checkout")->with('error', trans('admin/hardware/message.checkout.error'))->withErrors($asset->getErrors()); + return redirect()->back()->with('error', trans('admin/hardware/message.checkout.error'))->withErrors($asset->getErrors()); } From ea2f7617dfd7475fde3859d1e93802fe21007f98 Mon Sep 17 00:00:00 2001 From: snipe Date: Mon, 27 Nov 2017 21:20:12 -0800 Subject: [PATCH 07/13] Validate checkout_to_type on asset checkout --- app/Http/Requests/AssetCheckoutRequest.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/Http/Requests/AssetCheckoutRequest.php b/app/Http/Requests/AssetCheckoutRequest.php index d0991b308d..66b861525e 100644 --- a/app/Http/Requests/AssetCheckoutRequest.php +++ b/app/Http/Requests/AssetCheckoutRequest.php @@ -24,9 +24,10 @@ class AssetCheckoutRequest extends Request public function rules() { $rules = [ - "assigned_user" => 'required_without_all:assigned_asset,assigned_location', - "assigned_asset" => 'required_without_all:assigned_user,assigned_location|different:'.$this->id, - "assigned_location" => 'required_without_all:assigned_user,assigned_asset', + "assigned_user" => 'required_without_all:assigned_asset,assigned_location', + "assigned_asset" => 'required_without_all:assigned_user,assigned_location|different:'.$this->id, + "assigned_location" => 'required_without_all:assigned_user,assigned_asset', + "checkout_to_type" => 'required|in:asset,location,user' ]; From d8f404096c07f5dab5610cde157f718c4338f467 Mon Sep 17 00:00:00 2001 From: snipe Date: Mon, 27 Nov 2017 21:20:31 -0800 Subject: [PATCH 08/13] Added spacing in js --- public/mix-manifest.json | 4 ++-- resources/assets/js/snipeit.js | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/public/mix-manifest.json b/public/mix-manifest.json index 150723f8a2..e385227ab1 100644 --- a/public/mix-manifest.json +++ b/public/mix-manifest.json @@ -8,7 +8,7 @@ "/css/app.css.map": "/css/app.css.map?id=bdbe05e6ecd70ccfac72", "/css/overrides.css.map": "/css/overrides.css.map?id=898c91d4a425b01b589b", "/css/dist/all.css": "/css/dist/all.css?id=7c3842d2639193ac7e88", - "/js/dist/all.js": "/js/dist/all.js?id=7e993fb3b457ccc72b3f", + "/js/dist/all.js": "/js/dist/all.js?id=7b52ead3a55086ea1f8d", "/css/build/all.css": "/css/build/all.css?id=7c3842d2639193ac7e88", - "/js/build/all.js": "/js/build/all.js?id=7e993fb3b457ccc72b3f" + "/js/build/all.js": "/js/build/all.js?id=7b52ead3a55086ea1f8d" } \ No newline at end of file diff --git a/resources/assets/js/snipeit.js b/resources/assets/js/snipeit.js index ef0e1ba616..d58d7a704e 100755 --- a/resources/assets/js/snipeit.js +++ b/resources/assets/js/snipeit.js @@ -268,7 +268,7 @@ $(document).ready(function () { $('#assigned_user').hide(); $('#assigned_location').hide(); $('.notification-callout').fadeOut(); - + } else if (assignto_type == 'location') { $('#current_assets_box').fadeOut(); $('#assigned_asset').hide(); @@ -276,6 +276,7 @@ $(document).ready(function () { $('#assigned_location').show(); $('.notification-callout').fadeOut(); } else { + $('#assigned_asset').hide(); $('#assigned_user').show(); $('#assigned_location').hide(); @@ -283,7 +284,7 @@ $(document).ready(function () { $('#current_assets_box').fadeIn(); } $('.notification-callout').fadeIn(); - + } }); }); From 8af148174985f2e629877c1e8fa4b3dc7f9e88a2 Mon Sep 17 00:00:00 2001 From: snipe Date: Mon, 27 Nov 2017 21:20:38 -0800 Subject: [PATCH 09/13] Auto-bumped hash/version --- config/version.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config/version.php b/config/version.php index a47f78e2ca..c3ea4b9471 100644 --- a/config/version.php +++ b/config/version.php @@ -1,10 +1,10 @@ 'v4.1.6-pre', - 'full_app_version' => 'v4.1.6-pre - build 2787-g83c8449', - 'build_version' => '2787', + 'full_app_version' => 'v4.1.6-pre - build 2796-gfcc87b3', + 'build_version' => '2796', 'prerelease_version' => '', - 'hash_version' => 'g83c8449', - 'full_hash' => 'v4.1.5-57-g83c8449', + 'hash_version' => 'gfcc87b3', + 'full_hash' => 'v4.1.5-62-gfcc87b3', 'branch' => 'develop', ); \ No newline at end of file From 290cf79778e22195d42cdd2ef8e19e0389e21699 Mon Sep 17 00:00:00 2001 From: snipe Date: Mon, 27 Nov 2017 21:25:21 -0800 Subject: [PATCH 10/13] Auto-bumped hash/version --- config/version.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/version.php b/config/version.php index c3ea4b9471..4a4f12cadd 100644 --- a/config/version.php +++ b/config/version.php @@ -1,8 +1,8 @@ 'v4.1.6-pre', - 'full_app_version' => 'v4.1.6-pre - build 2796-gfcc87b3', - 'build_version' => '2796', + 'full_app_version' => 'v4.1.6-pre - build 2797-gfcc87b3', + 'build_version' => '2797', 'prerelease_version' => '', 'hash_version' => 'gfcc87b3', 'full_hash' => 'v4.1.5-62-gfcc87b3', From c0f791cf1377bd83319deec1ea44728a1800600d Mon Sep 17 00:00:00 2001 From: snipe Date: Mon, 27 Nov 2017 21:35:06 -0800 Subject: [PATCH 11/13] Sigh. --- app/Presenters/AssetPresenter.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/Presenters/AssetPresenter.php b/app/Presenters/AssetPresenter.php index 236003f614..f24d922531 100644 --- a/app/Presenters/AssetPresenter.php +++ b/app/Presenters/AssetPresenter.php @@ -289,10 +289,8 @@ class AssetPresenter extends Presenter $imagePath = ''; if ($this->image && !empty($this->image)) { $imagePath = $this->image; - return 'poop'; } elseif ($this->model && !empty($this->model->image)) { $imagePath = $this->model->image; - return 'fart'; } if (!empty($imagePath)) { return config('app.url').'/uploads/assets/'.$imagePath; From cdfd720c659d4a659b4ddb881d95ed4123a74a5e Mon Sep 17 00:00:00 2001 From: snipe Date: Mon, 27 Nov 2017 22:10:46 -0800 Subject: [PATCH 12/13] Fixed custom fields edit behavior with cutom format always selected --- app/Models/CustomField.php | 73 +++++++++++++++++-- .../views/custom_fields/fields/edit.blade.php | 8 +- 2 files changed, 71 insertions(+), 10 deletions(-) diff --git a/app/Models/CustomField.php b/app/Models/CustomField.php index 696b0454b5..350b1e8408 100644 --- a/app/Models/CustomField.php +++ b/app/Models/CustomField.php @@ -16,12 +16,17 @@ class CustomField extends Model public static $PredefinedFormats=[ "ANY" => "", "ALPHA" => "alpha", + "ALPHA-DASH" => "alpha_dash", + "NUMERIC" => "numeric", + "ALPHA-NUMERIC" => "alpha_num", "EMAIL" => "email", "DATE" => "date", "URL" => "url", - "NUMERIC" => "numeric", - "MAC" => "regex:/^[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}$/", "IP" => "ip", + "IPV4" => "ipv4", + "IPV6" => "ipv6", + "MAC" => "regex:/^[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}$/", + "BOOLEAN" => "boolean", ]; public $rules = [ @@ -30,27 +35,54 @@ class CustomField extends Model // This is confusing, since it's actually the custom fields table that // we're usually modifying, but since we alter the assets table, we have to - // say that here + // say that here, otherwise the new fields get added onto the custom fields + // table instead of the assets table. public static $table_name = "assets"; + + /** + * Convert the custom field's name property to a db-safe string. + * + * We could probably have used str_slug() here but not sure what it would + * do with previously existing values. - @snipe + * + * @author [A. Gianotto] [] + * @since [v3.4] + * @return String + */ public static function name_to_db_name($name) { return "_snipeit_" . preg_replace("/[^a-zA-Z0-9]/", "_", strtolower($name)); } + /** + * Set some boot methods for creating and updating. + * + * There is never ever a time when we wouldn't want to be updating those asset + * column names and the values of the db column name in the custom fields table + * if they have changed, so we handle that here so that we don't have to remember + * to do it in the controllers. + * + * @author [A. Gianotto] [] + * @since [v3.4] + * @return Boolean + */ public static function boot() { self::created(function ($custom_field) { - // column exists - nothing to do here + // Column already exists on the assets table - nothing to do here. + // This *shouldn't* happen in the wild. if (Schema::hasColumn(CustomField::$table_name, $custom_field->convertUnicodeDbSlug())) { return false; } + // Update the column name in the assets table Schema::table(CustomField::$table_name, function ($table) use ($custom_field) { $table->text($custom_field->convertUnicodeDbSlug())->nullable(); }); + // Update the db_column property in the custom fields table $custom_field->db_column = $custom_field->convertUnicodeDbSlug(); $custom_field->save(); }); @@ -58,8 +90,9 @@ class CustomField extends Model self::updating(function ($custom_field) { - // Column already exists. Nothing to update. + // Column already exists on the assets table - nothing to do here. if ($custom_field->isDirty("name")) { + if (Schema::hasColumn(CustomField::$table_name, $custom_field->convertUnicodeDbSlug())) { return true; } @@ -113,11 +146,22 @@ class CustomField extends Model return $this->db_column; } - // mutators for 'format' attribute + /** + * Mutator for the 'format' attribute. + * + * This is used by the dropdown to store the laravel-specific + * validator strings in the database but still return the + * user-friendly text in the dropdowns, and in the custom fields display. + * + * @author [A. Gianotto] [] + * @since [v3.4] + * @return Array + */ public function getFormatAttribute($value) { foreach (self::$PredefinedFormats as $name => $pattern) { - if ($pattern===$value) { + \Log::debug($name.'=>'.$pattern); + if ($pattern === $value) { return $name; } } @@ -168,6 +212,13 @@ class CustomField extends Model return $result; } + /** + * Check whether the field is encrypted + * + * @author [A. Gianotto] [] + * @since [v3.4] + * @return Boolean + */ public function isFieldDecryptable($string) { if (($this->field_encrypted=='1') && ($string!='')) { @@ -177,6 +228,14 @@ class CustomField extends Model } + /** + * Convert non-UTF-8 or weirdly encoded text into something that + * won't break the database. + * + * @author [A. Gianotto] [] + * @since [v3.4] + * @return Boolean + */ public function convertUnicodeDbSlug($original = null) { $name = $original ? $original : $this->name; diff --git a/resources/views/custom_fields/fields/edit.blade.php b/resources/views/custom_fields/fields/edit.blade.php index ff57ba2753..4422d33ca3 100644 --- a/resources/views/custom_fields/fields/edit.blade.php +++ b/resources/views/custom_fields/fields/edit.blade.php @@ -28,7 +28,6 @@
-
- {{ Form::select("format",\App\Helpers\Helper::predefined_formats(),"ANY", array('class'=>'format select2 form-control')) }} + {{ Form::select("format",\App\Helpers\Helper::predefined_formats(), $field->format, array('class'=>'format select2 form-control')) }} {!! $errors->first('format', ' :message') !!}
@@ -82,10 +81,12 @@ {{ trans('admin/custom_fields/general.field_custom_format') }}
- {{ Form::text('custom_format', Input::old('custom_format', (($field->format!='') && ($field->format!='ANY')) ? $field->format : ''), array('class' => 'form-control', 'id' => 'custom_format', 'placeholder'=>'regex:/^[0-9]{15}$/')) }} + + {{ Form::text('custom_format', Input::old('custom_format', (($field->format!='') && (stripos($field->format,'regex')===0)) ? $field->format : ''), array('class' => 'form-control', 'id' => 'custom_format', 'placeholder'=>'regex:/^[0-9]{15}$/')) }}

{!! trans('admin/custom_fields/general.field_custom_format_help') !!}

{!! $errors->first('custom_format', ' :message') !!} +
@@ -143,6 +144,7 @@ // If the custom_regex is ever NOT the last element in the format // listbox, we will need to refactor this. if ($('#custom_format').val()!='') { + // console.log('value is ' + $('#custom_format').val()); $('.format').prop('selectedIndex', $('.format')[0].options.length - 1); } From 8cf70e7e209777d4de791da9842a6080a95bcdcc Mon Sep 17 00:00:00 2001 From: snipe Date: Mon, 27 Nov 2017 22:10:54 -0800 Subject: [PATCH 13/13] Auto-bumped hash/version --- config/version.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/version.php b/config/version.php index 4a4f12cadd..89962fc935 100644 --- a/config/version.php +++ b/config/version.php @@ -1,8 +1,8 @@ 'v4.1.6-pre', - 'full_app_version' => 'v4.1.6-pre - build 2797-gfcc87b3', - 'build_version' => '2797', + 'full_app_version' => 'v4.1.6-pre - build 2800-gfcc87b3', + 'build_version' => '2800', 'prerelease_version' => '', 'hash_version' => 'gfcc87b3', 'full_hash' => 'v4.1.5-62-gfcc87b3',