mirror of
https://github.com/snipe/snipe-it.git
synced 2025-02-21 03:15:45 -08:00
This re-enables the ability to update encrypted custom fields via the API
This commit is contained in:
parent
d0f171ebc6
commit
67a8e0b5c6
|
@ -665,25 +665,26 @@ class AssetsController extends Controller
|
||||||
$model = AssetModel::find($asset->model_id);
|
$model = AssetModel::find($asset->model_id);
|
||||||
|
|
||||||
// Update custom fields
|
// Update custom fields
|
||||||
|
$problems_updating_encrypted_custom_fields = false;
|
||||||
if (($model) && (isset($model->fieldset))) {
|
if (($model) && (isset($model->fieldset))) {
|
||||||
foreach ($model->fieldset->fields as $field) {
|
foreach ($model->fieldset->fields as $field) {
|
||||||
$field_val = $request->input($field->db_column, null);
|
$field_val = $request->input($field->db_column, null);
|
||||||
|
|
||||||
if ($request->has($field->db_column)) {
|
if ($request->has($field->db_column)) {
|
||||||
if ($field->field_encrypted == '1') {
|
|
||||||
if (Gate::allows('admin')) {
|
|
||||||
$asset->{$field->db_column} = Crypt::encrypt($field_val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($field->element == 'checkbox') {
|
if ($field->element == 'checkbox') {
|
||||||
if(is_array($field_val)) {
|
if(is_array($field_val)) {
|
||||||
$field_val = implode(',', $field_val);
|
$field_val = implode(',', $field_val);
|
||||||
$asset->{$field->db_column} = $field_val;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
if ($field->field_encrypted == '1') {
|
||||||
$asset->{$field->db_column} = $field_val;
|
if (Gate::allows('admin')) {
|
||||||
|
$field_val = Crypt::encrypt($field_val);
|
||||||
|
} else {
|
||||||
|
$problems_updating_encrypted_custom_fields = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
$asset->{$field->db_column} = $field_val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -709,8 +710,11 @@ class AssetsController extends Controller
|
||||||
$asset->image = $asset->getImageUrl();
|
$asset->image = $asset->getImageUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.update.success')));
|
if ($problems_updating_encrypted_custom_fields) {
|
||||||
return response()->json(Helper::formatStandardApiResponse('success', (new AssetsTransformer)->transformAsset($asset), trans('admin/hardware/message.update.success')));
|
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.update.encrypted_warning')));
|
||||||
|
} else {
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.update.success')));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, $asset->getErrors()), 200);
|
return response()->json(Helper::formatStandardApiResponse('error', null, $asset->getErrors()), 200);
|
||||||
|
|
|
@ -353,6 +353,12 @@ class AssetFactory extends Factory
|
||||||
return $this->state(['requestable' => false]);
|
return $this->state(['requestable' => false]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function has_encrypted_custom_field()
|
||||||
|
{
|
||||||
|
return $this->state(['model_id' => AssetModel::where('name', 'asset with encrypted field')->first() ?? AssetModel::factory()->encrypted_field()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This allows bypassing model level validation if you want to purposefully
|
* This allows bypassing model level validation if you want to purposefully
|
||||||
* create an asset in an invalid state. Validation is turned back on
|
* create an asset in an invalid state. Validation is turned back on
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace Database\Factories;
|
namespace Database\Factories;
|
||||||
|
|
||||||
use App\Models\AssetModel;
|
use App\Models\AssetModel;
|
||||||
|
use App\Models\CustomField;
|
||||||
use App\Models\CustomFieldset;
|
use App\Models\CustomFieldset;
|
||||||
use App\Models\Depreciation;
|
use App\Models\Depreciation;
|
||||||
use App\Models\Manufacturer;
|
use App\Models\Manufacturer;
|
||||||
|
@ -429,4 +430,29 @@ class AssetModelFactory extends Factory
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function encrypted_field()
|
||||||
|
{
|
||||||
|
return $this->state(function () {
|
||||||
|
$field = CustomField::factory()->testEncrypted()->create(); // TODO - having to create and then 'find' the thing you just created is WEIRD
|
||||||
|
return [
|
||||||
|
'name' => 'asset with encrypted field',
|
||||||
|
'category_id' => function () {
|
||||||
|
return Category::where('name', 'Mobile Phones')->first() ?? Category::factory()->assetMobileCategory();
|
||||||
|
},
|
||||||
|
'manufacturer_id' => function () {
|
||||||
|
return Manufacturer::where('name', 'Apple')->first() ?? Manufacturer::factory()->apple();
|
||||||
|
},
|
||||||
|
'eol' => '12',
|
||||||
|
'depreciation_id' => function () {
|
||||||
|
return Depreciation::where('name', 'Computer Depreciation')->first() ?? Depreciation::factory()->computer();
|
||||||
|
},
|
||||||
|
'image' => 'iphone12.jpeg',
|
||||||
|
'fieldset_id' => function () use ($field) {
|
||||||
|
return CustomFieldset::where('name', 'Has Encrypted Custom Field')->first() ?? CustomFieldset::factory()->has_encrypted_custom_field()->hasAttached(CustomField::where('name', 'Test Encrypted')->first(), ['order' => 1, 'required' => 0], 'fields');
|
||||||
|
},
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace Database\Factories;
|
namespace Database\Factories;
|
||||||
|
|
||||||
use App\Models\CustomFieldset;
|
use App\Models\CustomFieldset;
|
||||||
|
use App\Models\CustomField;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
class CustomFieldsetFactory extends Factory
|
class CustomFieldsetFactory extends Factory
|
||||||
|
@ -43,4 +44,13 @@ class CustomFieldsetFactory extends Factory
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function has_encrypted_custom_field()
|
||||||
|
{
|
||||||
|
return $this->state(function () {
|
||||||
|
return [
|
||||||
|
'name' => 'Has Encrypted Custom Field',
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ return [
|
||||||
'update' => [
|
'update' => [
|
||||||
'error' => 'Asset was not updated, please try again',
|
'error' => 'Asset was not updated, please try again',
|
||||||
'success' => 'Asset updated successfully.',
|
'success' => 'Asset updated successfully.',
|
||||||
|
'encrypted_warning' => 'Asset updated successfully, but encrypted custom fields were not due to permissions',
|
||||||
'nothing_updated' => 'No fields were selected, so nothing was updated.',
|
'nothing_updated' => 'No fields were selected, so nothing was updated.',
|
||||||
'no_assets_selected' => 'No assets were selected, so nothing was updated.',
|
'no_assets_selected' => 'No assets were selected, so nothing was updated.',
|
||||||
'assets_do_not_exist_or_are_invalid' => 'Selected assets cannot be updated.',
|
'assets_do_not_exist_or_are_invalid' => 'Selected assets cannot be updated.',
|
||||||
|
|
|
@ -5,6 +5,8 @@ namespace Tests\Feature\Api\Assets;
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\AssetModel;
|
use App\Models\AssetModel;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
|
use App\Models\CustomField;
|
||||||
|
use App\Models\CustomFieldset;
|
||||||
use App\Models\Location;
|
use App\Models\Location;
|
||||||
use App\Models\Statuslabel;
|
use App\Models\Statuslabel;
|
||||||
use App\Models\Supplier;
|
use App\Models\Supplier;
|
||||||
|
@ -479,4 +481,36 @@ class AssetStoreTest extends TestCase
|
||||||
$json->has('messages.company_id')->etc();
|
$json->has('messages.company_id')->etc();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testEncryptedCustomField()
|
||||||
|
{
|
||||||
|
$field = CustomField::factory()->testEncrypted()->create();
|
||||||
|
$asset = Asset::factory()->has_encrypted_custom_field()->create();
|
||||||
|
$superuser = User::factory()->superuser()->create();
|
||||||
|
$normal_user = User::factory()->editAssets()->create();
|
||||||
|
|
||||||
|
//first, test that an Admin user can save the encrypted custom field
|
||||||
|
$response = $this->actingAsForApi($superuser)
|
||||||
|
->patchJson(route('api.assets.update', $asset->id), [
|
||||||
|
$field->db_column_name() => 'This is encrypted field'
|
||||||
|
])
|
||||||
|
->assertStatusMessageIs('success')
|
||||||
|
->assertOk()
|
||||||
|
->json();
|
||||||
|
$asset->refresh();
|
||||||
|
$this->assertEquals(\Crypt::decrypt($asset->{$field->db_column_name()}), 'This is encrypted field');
|
||||||
|
|
||||||
|
//next, test that a 'normal' user *cannot* change the encrypted custom field
|
||||||
|
$response = $this->actingAsForApi($normal_user)
|
||||||
|
->patchJson(route('api.assets.update', $asset->id), [
|
||||||
|
$field->db_column_name() => 'Some Other Value Entirely!'
|
||||||
|
])
|
||||||
|
->assertStatusMessageIs('success')
|
||||||
|
->assertOk()
|
||||||
|
->assertMessagesAre('Asset updated successfully, but encrypted custom fields were not due to permissions')
|
||||||
|
->json();
|
||||||
|
$asset->refresh();
|
||||||
|
$this->assertEquals(\Crypt::decrypt($asset->{$field->db_column_name()}), 'This is encrypted field');
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,5 +87,18 @@ trait CustomTestMacros
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
TestResponse::macro(
|
||||||
|
'assertMessagesAre',
|
||||||
|
function (string $message) {
|
||||||
|
Assert::assertEquals(
|
||||||
|
$message,
|
||||||
|
$this['messages'],
|
||||||
|
"Response messages was not {$message}"
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue