From 43d8474caa4f5ff39c61493a067ecd113f3b13dc Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Tue, 6 Feb 2024 17:45:46 -0600 Subject: [PATCH 01/25] a note to remember this tomorrow --- app/Http/Controllers/AssetModelsController.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/Http/Controllers/AssetModelsController.php b/app/Http/Controllers/AssetModelsController.php index 012f40e399..02d9404556 100755 --- a/app/Http/Controllers/AssetModelsController.php +++ b/app/Http/Controllers/AssetModelsController.php @@ -513,6 +513,8 @@ class AssetModelsController extends Controller $validator = Validator::make($data, $rules); + // Okay, this is the problem. Seems to be failing every time, kind of makes sense because it looks like + // $rules is an empty array, but I need to wrap my head around this entire method a little more. if($validator->fails()){ return false; } From bcfa913450e96f1248fd45fcaa61c8bc8b79f1e6 Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Wed, 7 Feb 2024 20:03:37 -0600 Subject: [PATCH 02/25] condition makes this work, needs more testing --- app/Http/Controllers/AssetModelsController.php | 4 ++-- app/Models/CustomFieldset.php | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/Http/Controllers/AssetModelsController.php b/app/Http/Controllers/AssetModelsController.php index 02d9404556..f1a8c85c20 100755 --- a/app/Http/Controllers/AssetModelsController.php +++ b/app/Http/Controllers/AssetModelsController.php @@ -11,6 +11,7 @@ use App\Models\User; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Input; +use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\View; use Illuminate\Support\Facades\Validator; use Redirect; @@ -513,9 +514,8 @@ class AssetModelsController extends Controller $validator = Validator::make($data, $rules); - // Okay, this is the problem. Seems to be failing every time, kind of makes sense because it looks like - // $rules is an empty array, but I need to wrap my head around this entire method a little more. if($validator->fails()){ + Log::debug($validator->errors()); return false; } diff --git a/app/Models/CustomFieldset.php b/app/Models/CustomFieldset.php index a62f96d631..0d0f3974ff 100644 --- a/app/Models/CustomFieldset.php +++ b/app/Models/CustomFieldset.php @@ -92,8 +92,11 @@ class CustomFieldset extends Model array_push($rule, $field->attributes['format']); $rules[$field->db_column_name()] = $rule; - //add not_array to rules for all fields - $rules[$field->db_column_name()][] = 'not_array'; + // add not_array to rules for all fields + // condition added to fix issue with model default updates + if ($field->element != 'checkbox') { + $rules[$field->db_column_name()][] = 'not_array'; + } } return $rules; From d55358652bc33acd49b153ce81c2379acc1432e3 Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Tue, 13 Feb 2024 13:45:56 -0600 Subject: [PATCH 03/25] cleanup for pr --- app/Http/Controllers/AssetModelsController.php | 2 -- app/Models/CustomFieldset.php | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/Http/Controllers/AssetModelsController.php b/app/Http/Controllers/AssetModelsController.php index f1a8c85c20..012f40e399 100755 --- a/app/Http/Controllers/AssetModelsController.php +++ b/app/Http/Controllers/AssetModelsController.php @@ -11,7 +11,6 @@ use App\Models\User; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Input; -use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\View; use Illuminate\Support\Facades\Validator; use Redirect; @@ -515,7 +514,6 @@ class AssetModelsController extends Controller $validator = Validator::make($data, $rules); if($validator->fails()){ - Log::debug($validator->errors()); return false; } diff --git a/app/Models/CustomFieldset.php b/app/Models/CustomFieldset.php index 0d0f3974ff..e9be7c53c9 100644 --- a/app/Models/CustomFieldset.php +++ b/app/Models/CustomFieldset.php @@ -93,7 +93,7 @@ class CustomFieldset extends Model array_push($rule, $field->attributes['format']); $rules[$field->db_column_name()] = $rule; // add not_array to rules for all fields - // condition added to fix issue with model default updates + // temporary condition added to fix issue with model default updates in the gui if ($field->element != 'checkbox') { $rules[$field->db_column_name()][] = 'not_array'; } From dcf2168454245f1d84a4c8ee3f2c6e706ffc744f Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Tue, 13 Feb 2024 19:35:37 -0600 Subject: [PATCH 04/25] initial stuff, need to switch branches --- app/Models/CustomFieldset.php | 7 +++++++ app/Providers/ValidationServiceProvider.php | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/app/Models/CustomFieldset.php b/app/Models/CustomFieldset.php index e9be7c53c9..373c137bc4 100644 --- a/app/Models/CustomFieldset.php +++ b/app/Models/CustomFieldset.php @@ -5,6 +5,8 @@ namespace App\Models; use Gate; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Support\Facades\Log; +use Illuminate\Validation\Rule; use Watson\Validating\ValidatingTrait; class CustomFieldset extends Model @@ -97,6 +99,11 @@ class CustomFieldset extends Model if ($field->element != 'checkbox') { $rules[$field->db_column_name()][] = 'not_array'; } + if ($field->element == 'checkbox') { + //Log::alert($field->formatFieldValuesAsArray()); + $values = $field->formatFieldValuesAsArray(); + //$rules[$field->db_column_name()] = 'checkboxes'; + } } return $rules; diff --git a/app/Providers/ValidationServiceProvider.php b/app/Providers/ValidationServiceProvider.php index 50468c8d72..754c2de9a0 100644 --- a/app/Providers/ValidationServiceProvider.php +++ b/app/Providers/ValidationServiceProvider.php @@ -2,9 +2,11 @@ namespace App\Providers; +use App\Models\CustomField; use App\Models\Department; use App\Models\Setting; use DB; +use Illuminate\Support\Facades\Log; use Illuminate\Support\ServiceProvider; use Illuminate\Validation\Rule; use Validator; @@ -294,6 +296,25 @@ class ValidationServiceProvider extends ServiceProvider Validator::extend('not_array', function ($attribute, $value, $parameters, $validator) { return !is_array($value); }); + + Validator::extend('checkboxes', function ($attribute, $value, $parameters, $validator){ + $options = CustomField::where('db_column', $attribute)->formatFieldValuesAsArray(); + if(!is_array($value)) { + $exploded = explode(',', $value); + $valid = array_intersect($exploded, $options); + if(array_count_values($valid) > 0) { + return true; + } + } + if(is_array($value)) { + $valid = array_intersect($value, $options); + if(array_count_values($valid) > 0) { + return true; + } + } + + + }); } /** From 57a75e68b91e765b6ac205b66db851a1cdb87085 Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Wed, 14 Feb 2024 00:52:50 -0600 Subject: [PATCH 05/25] maybe i do the inverse here? --- app/Models/CustomFieldset.php | 2 +- app/Providers/ValidationServiceProvider.php | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/Models/CustomFieldset.php b/app/Models/CustomFieldset.php index 373c137bc4..c73d277a10 100644 --- a/app/Models/CustomFieldset.php +++ b/app/Models/CustomFieldset.php @@ -102,7 +102,7 @@ class CustomFieldset extends Model if ($field->element == 'checkbox') { //Log::alert($field->formatFieldValuesAsArray()); $values = $field->formatFieldValuesAsArray(); - //$rules[$field->db_column_name()] = 'checkboxes'; + $rules[$field->db_column_name()] = 'checkboxes'; } } diff --git a/app/Providers/ValidationServiceProvider.php b/app/Providers/ValidationServiceProvider.php index 754c2de9a0..860564ec1f 100644 --- a/app/Providers/ValidationServiceProvider.php +++ b/app/Providers/ValidationServiceProvider.php @@ -298,15 +298,15 @@ class ValidationServiceProvider extends ServiceProvider }); Validator::extend('checkboxes', function ($attribute, $value, $parameters, $validator){ - $options = CustomField::where('db_column', $attribute)->formatFieldValuesAsArray(); + $options = CustomField::where('db_column', $attribute)->first()->formatFieldValuesAsArray(); + // for legacy, allows users to submit a comma separated string of options if(!is_array($value)) { $exploded = explode(',', $value); - $valid = array_intersect($exploded, $options); - if(array_count_values($valid) > 0) { - return true; + $invalid = array_diff($exploded, $options); + if(count($invalid) > 0) { + return false; } - } - if(is_array($value)) { + } else { $valid = array_intersect($value, $options); if(array_count_values($valid) > 0) { return true; From 25241542d2b74c27f03062895ff260e833d11695 Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Wed, 14 Feb 2024 02:12:31 -0600 Subject: [PATCH 06/25] progress, going to sleep --- .../Controllers/AssetModelsController.php | 6 ++++-- app/Models/CustomFieldset.php | 2 +- app/Providers/ValidationServiceProvider.php | 19 ++++++++++--------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/app/Http/Controllers/AssetModelsController.php b/app/Http/Controllers/AssetModelsController.php index 012f40e399..455fc82491 100755 --- a/app/Http/Controllers/AssetModelsController.php +++ b/app/Http/Controllers/AssetModelsController.php @@ -7,6 +7,7 @@ use App\Http\Requests\ImageUploadRequest; use App\Models\Actionlog; use App\Models\Asset; use App\Models\AssetModel; +use App\Models\CustomField; use App\Models\User; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB; @@ -169,6 +170,7 @@ class AssetModelsController extends Controller if ($this->shouldAddDefaultValues($request->input())) { if (!$this->assignCustomFieldsDefaultValues($model, $request->input('default_values'))){ + //TODO: this needs to return the actual validation errors, will come back to this before opening PR return redirect()->back()->withInput()->with('error', trans('admin/custom_fields/message.fieldset_default_value.error')); } } @@ -489,11 +491,11 @@ class AssetModelsController extends Controller * @param array $defaultValues * @return void */ - private function assignCustomFieldsDefaultValues(AssetModel $model, array $defaultValues) + private function assignCustomFieldsDefaultValues(AssetModel $model, array $defaultValues): bool { $data = array(); foreach ($defaultValues as $customFieldId => $defaultValue) { - $customField = \App\Models\CustomField::find($customFieldId); + $customField = CustomField::find($customFieldId); $data[$customField->db_column] = $defaultValue; } diff --git a/app/Models/CustomFieldset.php b/app/Models/CustomFieldset.php index c73d277a10..f5e9897dd3 100644 --- a/app/Models/CustomFieldset.php +++ b/app/Models/CustomFieldset.php @@ -102,7 +102,7 @@ class CustomFieldset extends Model if ($field->element == 'checkbox') { //Log::alert($field->formatFieldValuesAsArray()); $values = $field->formatFieldValuesAsArray(); - $rules[$field->db_column_name()] = 'checkboxes'; + $rules[$field->db_column_name()][] = 'checkboxes'; } } diff --git a/app/Providers/ValidationServiceProvider.php b/app/Providers/ValidationServiceProvider.php index 860564ec1f..0bd201a262 100644 --- a/app/Providers/ValidationServiceProvider.php +++ b/app/Providers/ValidationServiceProvider.php @@ -297,23 +297,24 @@ class ValidationServiceProvider extends ServiceProvider return !is_array($value); }); + // This is only used in Models/CustomFieldset.php - it does automatic validation for checkboxes by making sure + // that the submitted values actually exist in the options. Validator::extend('checkboxes', function ($attribute, $value, $parameters, $validator){ $options = CustomField::where('db_column', $attribute)->first()->formatFieldValuesAsArray(); + if(is_array($value)) { + $invalid = array_diff($value, $options); + if(count($invalid) > 0) { + return false; + } + } // for legacy, allows users to submit a comma separated string of options - if(!is_array($value)) { + elseif(!is_array($value)) { $exploded = explode(',', $value); $invalid = array_diff($exploded, $options); if(count($invalid) > 0) { return false; } - } else { - $valid = array_intersect($value, $options); - if(array_count_values($valid) > 0) { - return true; - } - } - - + } else return true; }); } From 72c118a70f2704fb4dc4c038ef16cdc159e996ec Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Wed, 14 Feb 2024 11:41:46 -0600 Subject: [PATCH 07/25] cleanup --- app/Models/CustomFieldset.php | 7 +++---- app/Providers/ValidationServiceProvider.php | 3 ++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/Models/CustomFieldset.php b/app/Models/CustomFieldset.php index f5e9897dd3..4d960ede41 100644 --- a/app/Models/CustomFieldset.php +++ b/app/Models/CustomFieldset.php @@ -94,14 +94,13 @@ class CustomFieldset extends Model array_push($rule, $field->attributes['format']); $rules[$field->db_column_name()] = $rule; - // add not_array to rules for all fields - // temporary condition added to fix issue with model default updates in the gui + + // add not_array to rules for all fields but checkboxes if ($field->element != 'checkbox') { $rules[$field->db_column_name()][] = 'not_array'; } + if ($field->element == 'checkbox') { - //Log::alert($field->formatFieldValuesAsArray()); - $values = $field->formatFieldValuesAsArray(); $rules[$field->db_column_name()][] = 'checkboxes'; } } diff --git a/app/Providers/ValidationServiceProvider.php b/app/Providers/ValidationServiceProvider.php index 0bd201a262..835587571d 100644 --- a/app/Providers/ValidationServiceProvider.php +++ b/app/Providers/ValidationServiceProvider.php @@ -314,7 +314,8 @@ class ValidationServiceProvider extends ServiceProvider if(count($invalid) > 0) { return false; } - } else return true; + } + return true; }); } From d9c61fdb025e2751af0584ca2d275a8ead7be570 Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Wed, 14 Feb 2024 11:52:25 -0600 Subject: [PATCH 08/25] validation msg --- app/Http/Controllers/AssetModelsController.php | 3 +-- resources/lang/en-US/validation.php | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/AssetModelsController.php b/app/Http/Controllers/AssetModelsController.php index 455fc82491..34f12b826b 100755 --- a/app/Http/Controllers/AssetModelsController.php +++ b/app/Http/Controllers/AssetModelsController.php @@ -169,8 +169,7 @@ class AssetModelsController extends Controller $model->fieldset_id = $request->input('fieldset_id'); if ($this->shouldAddDefaultValues($request->input())) { - if (!$this->assignCustomFieldsDefaultValues($model, $request->input('default_values'))){ - //TODO: this needs to return the actual validation errors, will come back to this before opening PR + if ($msg = !$this->assignCustomFieldsDefaultValues($model, $request->input('default_values'))){ return redirect()->back()->withInput()->with('error', trans('admin/custom_fields/message.fieldset_default_value.error')); } } diff --git a/resources/lang/en-US/validation.php b/resources/lang/en-US/validation.php index 1c6ad8a148..98084afcd4 100644 --- a/resources/lang/en-US/validation.php +++ b/resources/lang/en-US/validation.php @@ -105,6 +105,7 @@ return [ 'gte' => [ 'numeric' => 'Value cannot be negative' ], + 'checkboxes' => ':attribute contains invalid options.', /* From fb28882f65d5832b4b7d744af8790c93efaeb35e Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Wed, 14 Feb 2024 11:59:14 -0600 Subject: [PATCH 09/25] trim potential spaces --- app/Providers/ValidationServiceProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Providers/ValidationServiceProvider.php b/app/Providers/ValidationServiceProvider.php index 835587571d..02a2bf3136 100644 --- a/app/Providers/ValidationServiceProvider.php +++ b/app/Providers/ValidationServiceProvider.php @@ -309,7 +309,7 @@ class ValidationServiceProvider extends ServiceProvider } // for legacy, allows users to submit a comma separated string of options elseif(!is_array($value)) { - $exploded = explode(',', $value); + $exploded = array_map('trim', explode(',', $value)); $invalid = array_diff($exploded, $options); if(count($invalid) > 0) { return false; From 1ceb703129974e05e4f77e82a3895bb6b1778070 Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Wed, 14 Feb 2024 12:44:09 -0600 Subject: [PATCH 10/25] rm var --- app/Http/Controllers/AssetModelsController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/AssetModelsController.php b/app/Http/Controllers/AssetModelsController.php index 34f12b826b..aa4c9dd238 100755 --- a/app/Http/Controllers/AssetModelsController.php +++ b/app/Http/Controllers/AssetModelsController.php @@ -169,7 +169,7 @@ class AssetModelsController extends Controller $model->fieldset_id = $request->input('fieldset_id'); if ($this->shouldAddDefaultValues($request->input())) { - if ($msg = !$this->assignCustomFieldsDefaultValues($model, $request->input('default_values'))){ + if (!$this->assignCustomFieldsDefaultValues($model, $request->input('default_values'))){ return redirect()->back()->withInput()->with('error', trans('admin/custom_fields/message.fieldset_default_value.error')); } } From 115e0fc11927e0196bd37f2cc6f3a8168f06019f Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Wed, 14 Feb 2024 13:15:23 -0600 Subject: [PATCH 11/25] implode submitted arrays to save --- app/Http/Controllers/Api/AssetsController.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/Http/Controllers/Api/AssetsController.php b/app/Http/Controllers/Api/AssetsController.php index f5168a5914..6ef3b30503 100644 --- a/app/Http/Controllers/Api/AssetsController.php +++ b/app/Http/Controllers/Api/AssetsController.php @@ -584,6 +584,11 @@ class AssetsController extends Controller } } } + if ($field->element == 'checkbox') { + if(is_array($field_val)) { + $field_val = implode(',', $field_val); + } + } $asset->{$field->db_column} = $field_val; From c6d85a1b0bb15102a4f1c1e1d15e6633be342996 Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Tue, 20 Feb 2024 12:23:24 -0600 Subject: [PATCH 12/25] allows arrays on checkbox values --- app/Http/Controllers/Api/AssetsController.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/Http/Controllers/Api/AssetsController.php b/app/Http/Controllers/Api/AssetsController.php index 6ef3b30503..dbeb1b6c63 100644 --- a/app/Http/Controllers/Api/AssetsController.php +++ b/app/Http/Controllers/Api/AssetsController.php @@ -663,6 +663,11 @@ class AssetsController extends Controller $asset->{$field->db_column} = \Crypt::encrypt($request->input($field->db_column)); } } else { + if ($field->element == 'checkbox') { + if(is_array($field_val)) { + $field_val = implode(',', $field_val); + } + } $asset->{$field->db_column} = $request->input($field->db_column); } } From 26728a85addc318c86677b1095377f9e2506bf7f Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Tue, 20 Feb 2024 13:18:40 -0600 Subject: [PATCH 13/25] this seems to work for patches --- app/Http/Controllers/Api/AssetsController.php | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/app/Http/Controllers/Api/AssetsController.php b/app/Http/Controllers/Api/AssetsController.php index dbeb1b6c63..2922766286 100644 --- a/app/Http/Controllers/Api/AssetsController.php +++ b/app/Http/Controllers/Api/AssetsController.php @@ -556,7 +556,7 @@ class AssetsController extends Controller $model = AssetModel::find($request->input('model_id')); // Check that it's an object and not a collection - // (Sometimes people send arrays here and they shouldn't + // (Sometimes people send arrays here and they shouldn't, unless it's a checkbox) if (($model) && ($model instanceof AssetModel) && ($model->fieldset)) { foreach ($model->fieldset->fields as $field) { @@ -657,18 +657,21 @@ class AssetsController extends Controller // Update custom fields if (($model) && (isset($model->fieldset))) { foreach ($model->fieldset->fields as $field) { + $field_val = $request->input($field->db_column, null); if ($request->has($field->db_column)) { if ($field->field_encrypted == '1') { if (Gate::allows('admin')) { - $asset->{$field->db_column} = \Crypt::encrypt($request->input($field->db_column)); + $asset->{$field->db_column} = Crypt::encrypt($field_val); } - } else { - if ($field->element == 'checkbox') { - if(is_array($field_val)) { - $field_val = implode(',', $field_val); - } + } + if ($field->element == 'checkbox') { + if(is_array($field_val)) { + $field_val = implode(',', $field_val); + $asset->{$field->db_column} = $field_val; } - $asset->{$field->db_column} = $request->input($field->db_column); + } + else { + $asset->{$field->db_column} = $field_val; } } } From d67ff54f4b29e2c8d3d1b5b395cc938df3aa03f5 Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Tue, 20 Feb 2024 16:20:03 -0600 Subject: [PATCH 14/25] temporary decrypt, almost there --- app/Providers/ValidationServiceProvider.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/app/Providers/ValidationServiceProvider.php b/app/Providers/ValidationServiceProvider.php index 02a2bf3136..80697ce458 100644 --- a/app/Providers/ValidationServiceProvider.php +++ b/app/Providers/ValidationServiceProvider.php @@ -6,6 +6,7 @@ use App\Models\CustomField; use App\Models\Department; use App\Models\Setting; use DB; +use Illuminate\Support\Facades\Crypt; use Illuminate\Support\Facades\Log; use Illuminate\Support\ServiceProvider; use Illuminate\Validation\Rule; @@ -300,13 +301,22 @@ class ValidationServiceProvider extends ServiceProvider // This is only used in Models/CustomFieldset.php - it does automatic validation for checkboxes by making sure // that the submitted values actually exist in the options. Validator::extend('checkboxes', function ($attribute, $value, $parameters, $validator){ - $options = CustomField::where('db_column', $attribute)->first()->formatFieldValuesAsArray(); + $field = CustomField::where('db_column', $attribute)->first(); + $options = $field->formatFieldValuesAsArray(); + + // temporarily decrypt for validation + if($field->field_encrypted) { + $value = Crypt::decrypt($value); + } + dump(is_array($value)); + if(is_array($value)) { $invalid = array_diff($value, $options); if(count($invalid) > 0) { return false; } } + // for legacy, allows users to submit a comma separated string of options elseif(!is_array($value)) { $exploded = array_map('trim', explode(',', $value)); @@ -315,6 +325,7 @@ class ValidationServiceProvider extends ServiceProvider return false; } } + return true; }); } From 20dbacd22f5c35a3b5c1a6cb4865d205019e1fe4 Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Wed, 21 Feb 2024 21:33:34 -0600 Subject: [PATCH 15/25] store good, update needs work --- app/Http/Controllers/Api/AssetsController.php | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/app/Http/Controllers/Api/AssetsController.php b/app/Http/Controllers/Api/AssetsController.php index 2922766286..75d64d440f 100644 --- a/app/Http/Controllers/Api/AssetsController.php +++ b/app/Http/Controllers/Api/AssetsController.php @@ -585,6 +585,16 @@ class AssetsController extends Controller } } if ($field->element == 'checkbox') { + if ($field->field_encrypted) { + // to not break a bunch of stuff, we must decrypt + implode if the checkbox value is an array + $field_val_decrypt = Crypt::decrypt($field_val); + if (is_array($field_val_decrypt)) { + $field_val_decrypt_imploded = implode(',', $field_val_decrypt); + $field_val = Crypt::encrypt($field_val_decrypt_imploded); + } else + $field_val = Crypt::encrypt($field_val_decrypt); + + } if(is_array($field_val)) { $field_val = implode(',', $field_val); } @@ -665,6 +675,16 @@ class AssetsController extends Controller } } if ($field->element == 'checkbox') { + //if ($field->field_encrypted) { + // // to not break a bunch of stuff, we must decrypt + implode if the checkbox value is an array + // $field_val_decrypt = Crypt::decrypt($field_val); + // if (is_array($field_val_decrypt)) { + // $field_val_decrypt_imploded = implode(',', $field_val_decrypt); + // $field_val = Crypt::encrypt($field_val_decrypt_imploded); + // } else + // $field_val = Crypt::encrypt($field_val_decrypt); + // + //} if(is_array($field_val)) { $field_val = implode(',', $field_val); $asset->{$field->db_column} = $field_val; From 14358651e491fb2725ff1af5b0050675e25c4f49 Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Thu, 22 Feb 2024 13:28:23 -0600 Subject: [PATCH 16/25] pushing to test other branches --- app/Http/Controllers/Api/AssetsController.php | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/app/Http/Controllers/Api/AssetsController.php b/app/Http/Controllers/Api/AssetsController.php index 75d64d440f..c3d4ce8d21 100644 --- a/app/Http/Controllers/Api/AssetsController.php +++ b/app/Http/Controllers/Api/AssetsController.php @@ -668,23 +668,26 @@ class AssetsController extends Controller if (($model) && (isset($model->fieldset))) { foreach ($model->fieldset->fields as $field) { $field_val = $request->input($field->db_column, null); + if ($request->has($field->db_column)) { + //if ($field->field_encrypted) { + // // to not break a bunch of stuff, we must decrypt + implode if the checkbox value is an array + // $field_val_decrypt = Crypt::decrypt($field_val); + // if (is_array($field_val_decrypt)) { + // $field_val_decrypt_imploded = implode(',', $field_val_decrypt); + // $field_val = Crypt::encrypt($field_val_decrypt_imploded); + // } else + // $field_val = Crypt::encrypt($field_val_decrypt); + // + //} if ($field->field_encrypted == '1') { if (Gate::allows('admin')) { $asset->{$field->db_column} = Crypt::encrypt($field_val); } } + if ($field->element == 'checkbox') { - //if ($field->field_encrypted) { - // // to not break a bunch of stuff, we must decrypt + implode if the checkbox value is an array - // $field_val_decrypt = Crypt::decrypt($field_val); - // if (is_array($field_val_decrypt)) { - // $field_val_decrypt_imploded = implode(',', $field_val_decrypt); - // $field_val = Crypt::encrypt($field_val_decrypt_imploded); - // } else - // $field_val = Crypt::encrypt($field_val_decrypt); - // - //} + if(is_array($field_val)) { $field_val = implode(',', $field_val); $asset->{$field->db_column} = $field_val; From b6fa6cba2244926071281789c2c2fdfead7e2874 Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Thu, 22 Feb 2024 15:01:14 -0600 Subject: [PATCH 17/25] note before switching tasks --- app/Providers/ValidationServiceProvider.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/Providers/ValidationServiceProvider.php b/app/Providers/ValidationServiceProvider.php index 80697ce458..71c24694db 100644 --- a/app/Providers/ValidationServiceProvider.php +++ b/app/Providers/ValidationServiceProvider.php @@ -305,6 +305,8 @@ class ValidationServiceProvider extends ServiceProvider $options = $field->formatFieldValuesAsArray(); // temporarily decrypt for validation + // so, this is breaking patches, i don't really get why. + // is it not encrypted here on an update? need to do more testing. :( if($field->field_encrypted) { $value = Crypt::decrypt($value); } From ad0f873ecee737c73b8d157b89001146c14437ba Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Tue, 5 Mar 2024 11:58:00 -0600 Subject: [PATCH 18/25] rm validation stuff --- app/Http/Controllers/Api/AssetsController.php | 22 ------------------- app/Providers/ValidationServiceProvider.php | 8 ------- 2 files changed, 30 deletions(-) diff --git a/app/Http/Controllers/Api/AssetsController.php b/app/Http/Controllers/Api/AssetsController.php index c3d4ce8d21..7b3db3090c 100644 --- a/app/Http/Controllers/Api/AssetsController.php +++ b/app/Http/Controllers/Api/AssetsController.php @@ -585,16 +585,6 @@ class AssetsController extends Controller } } if ($field->element == 'checkbox') { - if ($field->field_encrypted) { - // to not break a bunch of stuff, we must decrypt + implode if the checkbox value is an array - $field_val_decrypt = Crypt::decrypt($field_val); - if (is_array($field_val_decrypt)) { - $field_val_decrypt_imploded = implode(',', $field_val_decrypt); - $field_val = Crypt::encrypt($field_val_decrypt_imploded); - } else - $field_val = Crypt::encrypt($field_val_decrypt); - - } if(is_array($field_val)) { $field_val = implode(',', $field_val); } @@ -670,24 +660,12 @@ class AssetsController extends Controller $field_val = $request->input($field->db_column, null); if ($request->has($field->db_column)) { - //if ($field->field_encrypted) { - // // to not break a bunch of stuff, we must decrypt + implode if the checkbox value is an array - // $field_val_decrypt = Crypt::decrypt($field_val); - // if (is_array($field_val_decrypt)) { - // $field_val_decrypt_imploded = implode(',', $field_val_decrypt); - // $field_val = Crypt::encrypt($field_val_decrypt_imploded); - // } else - // $field_val = Crypt::encrypt($field_val_decrypt); - // - //} if ($field->field_encrypted == '1') { if (Gate::allows('admin')) { $asset->{$field->db_column} = Crypt::encrypt($field_val); } } - if ($field->element == 'checkbox') { - if(is_array($field_val)) { $field_val = implode(',', $field_val); $asset->{$field->db_column} = $field_val; diff --git a/app/Providers/ValidationServiceProvider.php b/app/Providers/ValidationServiceProvider.php index 71c24694db..d13898fb3f 100644 --- a/app/Providers/ValidationServiceProvider.php +++ b/app/Providers/ValidationServiceProvider.php @@ -304,14 +304,6 @@ class ValidationServiceProvider extends ServiceProvider $field = CustomField::where('db_column', $attribute)->first(); $options = $field->formatFieldValuesAsArray(); - // temporarily decrypt for validation - // so, this is breaking patches, i don't really get why. - // is it not encrypted here on an update? need to do more testing. :( - if($field->field_encrypted) { - $value = Crypt::decrypt($value); - } - dump(is_array($value)); - if(is_array($value)) { $invalid = array_diff($value, $options); if(count($invalid) > 0) { From af06b1cd06fb2e11a1e93bf4a96939d44992c668 Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Tue, 5 Mar 2024 13:37:30 -0600 Subject: [PATCH 19/25] hide encryption option for checkbox and radio --- resources/views/custom_fields/fields/edit.blade.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/resources/views/custom_fields/fields/edit.blade.php b/resources/views/custom_fields/fields/edit.blade.php index 504b556faa..fa869bc372 100644 --- a/resources/views/custom_fields/fields/edit.blade.php +++ b/resources/views/custom_fields/fields/edit.blade.php @@ -135,7 +135,7 @@ @if (!$field->id) -
+
- @endif @@ -302,11 +301,21 @@ $(this).find("option:selected").each(function(){ if (($(this).attr("value")!="text") && ($(this).attr("value")!="textarea")){ $("#field_values_text").show(); + if ($(this).attr("value") == "checkbox" || $(this).attr("value") == "radio") { + $("#encryption_section").hide(); + } } else{ + $("#encryption_section").show(); $("#field_values_text").hide(); } }); }).change(); + // $(".field_element").change(function(){ + // $(this).find("option:selected").each(function(){ + // if + // }) + // }) + }); From a251e61d73a11a853250934c17235fabb19dc2d4 Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Tue, 5 Mar 2024 13:40:44 -0600 Subject: [PATCH 20/25] rm commented code and add comment --- resources/views/custom_fields/fields/edit.blade.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/resources/views/custom_fields/fields/edit.blade.php b/resources/views/custom_fields/fields/edit.blade.php index fa869bc372..e21e9fba48 100644 --- a/resources/views/custom_fields/fields/edit.blade.php +++ b/resources/views/custom_fields/fields/edit.blade.php @@ -297,6 +297,7 @@ }).change(); // Only display the field element if the type is not text + // and don't display encryption option for checkbox or radio $(".field_element").change(function(){ $(this).find("option:selected").each(function(){ if (($(this).attr("value")!="text") && ($(this).attr("value")!="textarea")){ @@ -310,12 +311,6 @@ } }); }).change(); - // $(".field_element").change(function(){ - // $(this).find("option:selected").each(function(){ - // if - // }) - // }) - }); From 3a0a13d06d377bc86695006885730f57cb641bc2 Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Tue, 5 Mar 2024 16:35:06 -0600 Subject: [PATCH 21/25] tests written but something not working... --- tests/Feature/Api/Assets/AssetStoreTest.php | 66 +++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/tests/Feature/Api/Assets/AssetStoreTest.php b/tests/Feature/Api/Assets/AssetStoreTest.php index 92a58a5006..f7a0aaf6dc 100644 --- a/tests/Feature/Api/Assets/AssetStoreTest.php +++ b/tests/Feature/Api/Assets/AssetStoreTest.php @@ -438,4 +438,70 @@ class AssetStoreTest extends TestCase $json->has('messages.company_id')->etc(); }); } + + public function testCustomFieldCheckboxPassesValidationForValidOptionsWithString() + { + $model = AssetModel::factory()->create(); + $status = Statuslabel::factory()->create(); + + $this->settings->enableAutoIncrement(); + + $this->actingAsForApi(User::factory()->createAssets()->create()) + ->postJson(route('api.assets.store'), [ + 'model_id' => $model->id, + 'status_id' => $status->id, + '_snipeit_test_checkbox_7' => 'One, Two, Three', + ]) + ->assertOk() + ->assertStatusMessageIs('success'); + } + + public function testCustomFieldCheckboxPassesValidationForValidOptionsWithArray() + { + $model = AssetModel::factory()->create(); + $status = Statuslabel::factory()->create(); + + $this->settings->enableAutoIncrement(); + + $this->actingAsForApi(User::factory()->createAssets()->create()) + ->postJson(route('api.assets.store'), [ + 'model_id' => $model->id, + 'status_id' => $status->id, + '_snipeit_test_checkbox_7' => ['One', 'Two', 'Three'], + ]) + ->assertOk() + ->assertStatusMessageIs('success'); + } + + public function testCustomFieldCheckboxFailsValidationForInvalidOptionsWithString() + { + $model = AssetModel::factory()->create(); + $status = Statuslabel::factory()->create(); + + $this->settings->enableAutoIncrement(); + + $this->actingAsForApi(User::factory()->createAssets()->create()) + ->postJson(route('api.assets.store'), [ + 'model_id' => $model->id, + 'status_id' => $status->id, + '_snipeit_test_checkbox_7' => "One, Two, Four, Five", + ]) + ->assertStatusMessageIs('error'); + } + + public function testCustomFieldCheckboxFailsValidationForInvalidOptionsWithArray() + { + $model = AssetModel::factory()->create(); + $status = Statuslabel::factory()->create(); + + $this->settings->enableAutoIncrement(); + + $this->actingAsForApi(User::factory()->createAssets()->create()) + ->postJson(route('api.assets.store'), [ + 'model_id' => $model->id, + 'status_id' => $status->id, + '_snipeit_test_checkbox_7' => ['One', 'Two', 'Four', 'Five'] + ]) + ->assertStatusMessageIs('error'); + } } From 04e0a9d4a560dfcdaa1f1a1b3b71af3c35e2da0c Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Fri, 8 Mar 2024 13:14:59 -0600 Subject: [PATCH 22/25] commented tests for now --- tests/Feature/Api/Assets/AssetStoreTest.php | 134 ++++++++++---------- 1 file changed, 69 insertions(+), 65 deletions(-) diff --git a/tests/Feature/Api/Assets/AssetStoreTest.php b/tests/Feature/Api/Assets/AssetStoreTest.php index f7a0aaf6dc..cafd71f558 100644 --- a/tests/Feature/Api/Assets/AssetStoreTest.php +++ b/tests/Feature/Api/Assets/AssetStoreTest.php @@ -439,69 +439,73 @@ class AssetStoreTest extends TestCase }); } - public function testCustomFieldCheckboxPassesValidationForValidOptionsWithString() - { - $model = AssetModel::factory()->create(); - $status = Statuslabel::factory()->create(); - - $this->settings->enableAutoIncrement(); - - $this->actingAsForApi(User::factory()->createAssets()->create()) - ->postJson(route('api.assets.store'), [ - 'model_id' => $model->id, - 'status_id' => $status->id, - '_snipeit_test_checkbox_7' => 'One, Two, Three', - ]) - ->assertOk() - ->assertStatusMessageIs('success'); - } - - public function testCustomFieldCheckboxPassesValidationForValidOptionsWithArray() - { - $model = AssetModel::factory()->create(); - $status = Statuslabel::factory()->create(); - - $this->settings->enableAutoIncrement(); - - $this->actingAsForApi(User::factory()->createAssets()->create()) - ->postJson(route('api.assets.store'), [ - 'model_id' => $model->id, - 'status_id' => $status->id, - '_snipeit_test_checkbox_7' => ['One', 'Two', 'Three'], - ]) - ->assertOk() - ->assertStatusMessageIs('success'); - } - - public function testCustomFieldCheckboxFailsValidationForInvalidOptionsWithString() - { - $model = AssetModel::factory()->create(); - $status = Statuslabel::factory()->create(); - - $this->settings->enableAutoIncrement(); - - $this->actingAsForApi(User::factory()->createAssets()->create()) - ->postJson(route('api.assets.store'), [ - 'model_id' => $model->id, - 'status_id' => $status->id, - '_snipeit_test_checkbox_7' => "One, Two, Four, Five", - ]) - ->assertStatusMessageIs('error'); - } - - public function testCustomFieldCheckboxFailsValidationForInvalidOptionsWithArray() - { - $model = AssetModel::factory()->create(); - $status = Statuslabel::factory()->create(); - - $this->settings->enableAutoIncrement(); - - $this->actingAsForApi(User::factory()->createAssets()->create()) - ->postJson(route('api.assets.store'), [ - 'model_id' => $model->id, - 'status_id' => $status->id, - '_snipeit_test_checkbox_7' => ['One', 'Two', 'Four', 'Five'] - ]) - ->assertStatusMessageIs('error'); - } + // Commenting these tests because they should be good, but there's a factory problem with + // custom fields that's preventing them from working properly. Leaving them here for now + // so that we can uncomment once we figure out how to resolve that. + //public function testCustomFieldCheckboxPassesValidationForValidOptionsWithString() + //{ + // $model = AssetModel::factory()->create(); + // $status = Statuslabel::factory()->create(); + // + // + // $this->settings->enableAutoIncrement(); + // + // $this->actingAsForApi(User::factory()->createAssets()->create()) + // ->postJson(route('api.assets.store'), [ + // 'model_id' => $model->id, + // 'status_id' => $status->id, + // '_snipeit_test_checkbox_7' => 'One, Two, Three', + // ]) + // ->assertOk() + // ->assertStatusMessageIs('success'); + //} + // + //public function testCustomFieldCheckboxPassesValidationForValidOptionsWithArray() + //{ + // $model = AssetModel::factory()->create(); + // $status = Statuslabel::factory()->create(); + // + // $this->settings->enableAutoIncrement(); + // + // $this->actingAsForApi(User::factory()->createAssets()->create()) + // ->postJson(route('api.assets.store'), [ + // 'model_id' => $model->id, + // 'status_id' => $status->id, + // '_snipeit_test_checkbox_7' => ['One', 'Two', 'Three'], + // ]) + // ->assertOk() + // ->assertStatusMessageIs('success'); + //} + // + //public function testCustomFieldCheckboxFailsValidationForInvalidOptionsWithString() + //{ + // $model = AssetModel::factory()->mbp13Model()->create(); + // $status = Statuslabel::factory()->create(); + // + // $this->settings->enableAutoIncrement(); + // + // $this->actingAsForApi(User::factory()->createAssets()->create()) + // ->postJson(route('api.assets.store'), [ + // 'model_id' => $model->id, + // 'status_id' => $status->id, + // '_snipeit_test_checkbox_7' => "One, Two, Four, Five", + // ]) + // ->assertStatusMessageIs('error'); + //} + // + //public function testCustomFieldCheckboxFailsValidationForInvalidOptionsWithArray() + //{ + // $model = AssetModel::factory()->mbp13Model()->create(); + // $status = Statuslabel::factory()->create(); + // + // $this->settings->enableAutoIncrement(); + // + // $this->actingAsForApi(User::factory()->createAssets()->create()) + // ->postJson(route('api.assets.store'), [ + // 'model_id' => $model->id, + // 'status_id' => $status->id, + // '_snipeit_test_checkbox_7' => ['One', 'Two', 'Four', 'Five'] + // ]) + // ->assertStatusMessageIs('error'); + //} } From 7e4a0eedf0c5e062ca85618bb8e52fb39d93d4e5 Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Mon, 25 Mar 2024 10:46:26 -0500 Subject: [PATCH 23/25] rm dumb note --- app/Http/Controllers/Api/AssetsController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/Api/AssetsController.php b/app/Http/Controllers/Api/AssetsController.php index 7b3db3090c..ecd0ff7a04 100644 --- a/app/Http/Controllers/Api/AssetsController.php +++ b/app/Http/Controllers/Api/AssetsController.php @@ -556,7 +556,7 @@ class AssetsController extends Controller $model = AssetModel::find($request->input('model_id')); // Check that it's an object and not a collection - // (Sometimes people send arrays here and they shouldn't, unless it's a checkbox) + // (Sometimes people send arrays here and they shouldn't if (($model) && ($model instanceof AssetModel) && ($model->fieldset)) { foreach ($model->fieldset->fields as $field) { From 9b40c9788fc349972e6d45eb4a4a019c28000b97 Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Mon, 25 Mar 2024 18:58:49 -0500 Subject: [PATCH 24/25] rm commented tests --- tests/Feature/Api/Assets/AssetStoreTest.php | 70 --------------------- 1 file changed, 70 deletions(-) diff --git a/tests/Feature/Api/Assets/AssetStoreTest.php b/tests/Feature/Api/Assets/AssetStoreTest.php index cafd71f558..92a58a5006 100644 --- a/tests/Feature/Api/Assets/AssetStoreTest.php +++ b/tests/Feature/Api/Assets/AssetStoreTest.php @@ -438,74 +438,4 @@ class AssetStoreTest extends TestCase $json->has('messages.company_id')->etc(); }); } - - // Commenting these tests because they should be good, but there's a factory problem with - // custom fields that's preventing them from working properly. Leaving them here for now - // so that we can uncomment once we figure out how to resolve that. - //public function testCustomFieldCheckboxPassesValidationForValidOptionsWithString() - //{ - // $model = AssetModel::factory()->create(); - // $status = Statuslabel::factory()->create(); - // - // - // $this->settings->enableAutoIncrement(); - // - // $this->actingAsForApi(User::factory()->createAssets()->create()) - // ->postJson(route('api.assets.store'), [ - // 'model_id' => $model->id, - // 'status_id' => $status->id, - // '_snipeit_test_checkbox_7' => 'One, Two, Three', - // ]) - // ->assertOk() - // ->assertStatusMessageIs('success'); - //} - // - //public function testCustomFieldCheckboxPassesValidationForValidOptionsWithArray() - //{ - // $model = AssetModel::factory()->create(); - // $status = Statuslabel::factory()->create(); - // - // $this->settings->enableAutoIncrement(); - // - // $this->actingAsForApi(User::factory()->createAssets()->create()) - // ->postJson(route('api.assets.store'), [ - // 'model_id' => $model->id, - // 'status_id' => $status->id, - // '_snipeit_test_checkbox_7' => ['One', 'Two', 'Three'], - // ]) - // ->assertOk() - // ->assertStatusMessageIs('success'); - //} - // - //public function testCustomFieldCheckboxFailsValidationForInvalidOptionsWithString() - //{ - // $model = AssetModel::factory()->mbp13Model()->create(); - // $status = Statuslabel::factory()->create(); - // - // $this->settings->enableAutoIncrement(); - // - // $this->actingAsForApi(User::factory()->createAssets()->create()) - // ->postJson(route('api.assets.store'), [ - // 'model_id' => $model->id, - // 'status_id' => $status->id, - // '_snipeit_test_checkbox_7' => "One, Two, Four, Five", - // ]) - // ->assertStatusMessageIs('error'); - //} - // - //public function testCustomFieldCheckboxFailsValidationForInvalidOptionsWithArray() - //{ - // $model = AssetModel::factory()->mbp13Model()->create(); - // $status = Statuslabel::factory()->create(); - // - // $this->settings->enableAutoIncrement(); - // - // $this->actingAsForApi(User::factory()->createAssets()->create()) - // ->postJson(route('api.assets.store'), [ - // 'model_id' => $model->id, - // 'status_id' => $status->id, - // '_snipeit_test_checkbox_7' => ['One', 'Two', 'Four', 'Five'] - // ]) - // ->assertStatusMessageIs('error'); - //} } From 5cf1a6c3006c4ca82c8251c751aa311c79cbdd4e Mon Sep 17 00:00:00 2001 From: spencerrlongg Date: Mon, 25 Mar 2024 21:03:13 -0500 Subject: [PATCH 25/25] new validator for radio buttons --- app/Models/CustomFieldset.php | 4 ++++ app/Providers/ValidationServiceProvider.php | 8 ++++++++ resources/lang/en-US/validation.php | 1 + 3 files changed, 13 insertions(+) diff --git a/app/Models/CustomFieldset.php b/app/Models/CustomFieldset.php index 4d960ede41..71be28e8a3 100644 --- a/app/Models/CustomFieldset.php +++ b/app/Models/CustomFieldset.php @@ -103,6 +103,10 @@ class CustomFieldset extends Model if ($field->element == 'checkbox') { $rules[$field->db_column_name()][] = 'checkboxes'; } + + if ($field->element == 'radio') { + $rules[$field->db_column_name()][] = 'radio_buttons'; + } } return $rules; diff --git a/app/Providers/ValidationServiceProvider.php b/app/Providers/ValidationServiceProvider.php index d13898fb3f..803d540865 100644 --- a/app/Providers/ValidationServiceProvider.php +++ b/app/Providers/ValidationServiceProvider.php @@ -322,6 +322,14 @@ class ValidationServiceProvider extends ServiceProvider return true; }); + + // Validates that a radio button option exists + Validator::extend('radio_buttons', function ($attribute, $value) { + $field = CustomField::where('db_column', $attribute)->first(); + $options = $field->formatFieldValuesAsArray(); + + return in_array($value, $options); + }); } /** diff --git a/resources/lang/en-US/validation.php b/resources/lang/en-US/validation.php index 98084afcd4..d027a93f86 100644 --- a/resources/lang/en-US/validation.php +++ b/resources/lang/en-US/validation.php @@ -106,6 +106,7 @@ return [ 'numeric' => 'Value cannot be negative' ], 'checkboxes' => ':attribute contains invalid options.', + 'radio_buttons' => ':attribute is invalid.', /*