diff --git a/app/Console/Commands/SyncAssetLocations.php b/app/Console/Commands/SyncAssetLocations.php
index a98cedcdb..98279eca3 100644
--- a/app/Console/Commands/SyncAssetLocations.php
+++ b/app/Console/Commands/SyncAssetLocations.php
@@ -49,7 +49,7 @@ class SyncAssetLocations extends Command
$bar = $this->output->createProgressBar(count($total_assets));
// Unassigned
- $rtd_assets = Asset::whereNull('assigned_to')->with('defaultLoc')->get();
+ $rtd_assets = Asset::whereNull('assigned_to')->whereNull('deleted_at')->with('defaultLoc')->get();
$output['info'][] = 'There are '.$rtd_assets->count().' unassigned assets.';
foreach ($rtd_assets as $rtd_asset) {
@@ -60,15 +60,15 @@ class SyncAssetLocations extends Command
$bar->advance();
}
- $assigned_user_assets = Asset::where('assigned_type','App\Models\User')->whereNotNull('assigned_to')->get();
+ $assigned_user_assets = Asset::where('assigned_type','App\Models\User')->whereNotNull('assigned_to')->whereNull('deleted_at')->get();
$output['info'][] = 'There are '.$assigned_user_assets->count().' assets checked out to users.';
foreach ($assigned_user_assets as $assigned_user_asset) {
if (($assigned_user_asset->assignedTo) && ($assigned_user_asset->assignedTo->userLoc)) {
$new_location=$assigned_user_asset->assignedTo->userloc->id;
$output['info'][] ='Setting User Asset ' . $assigned_user_asset->id . ' ('.$assigned_user_asset->asset_tag.') to ' . $assigned_user_asset->assignedTo->userLoc->name . ' which is id: ' . $new_location;
} else {
- $output['error'][] ='Asset ' . $assigned_user_asset->id . ' ('.$assigned_user_asset->asset_tag.') still has no location! ';
- $new_location=$assigned_user_asset->rtd_location_id;
+ $output['warn'][] ='Asset ' . $assigned_user_asset->id . ' ('.$assigned_user_asset->asset_tag.') still has no location! ';
+ $new_location = $assigned_user_asset->rtd_location_id;
}
$assigned_user_asset->location_id=$new_location;
$assigned_user_asset->unsetEventDispatcher();
@@ -78,34 +78,45 @@ class SyncAssetLocations extends Command
}
$assigned_location_assets = Asset::where('assigned_type','App\Models\Location')
- ->whereNotNull('assigned_to')->get();
+ ->whereNotNull('assigned_to')->whereNull('deleted_at')->get();
$output['info'][] = 'There are '.$assigned_location_assets->count().' assets checked out to locations.';
foreach ($assigned_location_assets as $assigned_location_asset) {
- $assigned_location_asset->location_id = $assigned_location_asset->assignedTo->id;
-
- $output['info'][] ='Setting Location Assigned asset ' . $assigned_location_asset->id . ' ('.$assigned_location_asset->asset_tag.') that is checked out to '.$assigned_location_asset->assignedTo->name.' (#'.$assigned_location_asset->assignedTo->id.') to location: ' . $assigned_location_asset->assetLoc()->id;
- $assigned_location_asset->unsetEventDispatcher();
- $assigned_location_asset->save();
+ if ($assigned_location_asset->assignedTo) {
+ $assigned_location_asset->location_id = $assigned_location_asset->assignedTo->id;
+ $output['info'][] ='Setting Location Assigned asset ' . $assigned_location_asset->id . ' ('.$assigned_location_asset->asset_tag.') that is checked out to '.$assigned_location_asset->assignedTo->name.' (#'.$assigned_location_asset->assignedTo->id.') to location: ' . $assigned_location_asset->assetLoc()->id;
+ $assigned_location_asset->unsetEventDispatcher();
+ $assigned_location_asset->save();
+ } else {
+ $output['warn'][] ='Asset ' . $assigned_location_asset->id . ' ('.$assigned_location_asset->asset_tag.') did not return a valid associated location - perhaps it was deleted?';
+ }
$bar->advance();
+
}
// Assigned to assets
$assigned_asset_assets = Asset::where('assigned_type','App\Models\Asset')
- ->whereNotNull('assigned_to')->get();
+ ->whereNotNull('assigned_to')->whereNull('deleted_at')->get();
$output['info'][] ='Asset-assigned assets: '.$assigned_asset_assets->count();
foreach ($assigned_asset_assets as $assigned_asset_asset) {
- $assigned_asset_asset->location_id = $assigned_asset_asset->assetLoc()->id;
- $output['info'][] ='Setting Asset Assigned asset ' . $assigned_asset_asset->assetLoc()->id. ' ('.$assigned_asset_asset->asset_tag.') location to: ' . $assigned_asset_asset->assetLoc()->id;
- $assigned_asset_asset->unsetEventDispatcher();
- $assigned_asset_asset->save();
+
+ // Check to make sure there aren't any invalid relationships
+ if ($assigned_asset_asset->assetLoc()) {
+ $assigned_asset_asset->location_id = $assigned_asset_asset->assetLoc()->id;
+ $output['info'][] ='Setting Asset Assigned asset ' . $assigned_asset_asset->assetLoc()->id. ' ('.$assigned_asset_asset->asset_tag.') location to: ' . $assigned_asset_asset->assetLoc()->id;
+ $assigned_asset_asset->unsetEventDispatcher();
+ $assigned_asset_asset->save();
+ } else {
+ $output['warn'][] ='Asset Assigned asset ' . $assigned_asset_asset->assetLoc()->id. ' ('.$assigned_asset_asset->asset_tag.') does not seem to have a valid location';
+ }
+
$bar->advance();
}
- $unlocated_assets = Asset::whereNull("location_id")->get();
+ $unlocated_assets = Asset::whereNull("location_id")->whereNull('deleted_at')->get();
$output['info'][] ='Assets still without a location: '.$unlocated_assets->count();
foreach($unlocated_assets as $unlocated_asset) {
$output['warn'][] ='Asset: '.$unlocated_asset->id.' still has no location. ';
diff --git a/app/Http/Controllers/CategoriesController.php b/app/Http/Controllers/CategoriesController.php
index f1ccb1066..1dbe7488f 100755
--- a/app/Http/Controllers/CategoriesController.php
+++ b/app/Http/Controllers/CategoriesController.php
@@ -71,9 +71,7 @@ class CategoriesController extends Controller
*/
public function store(ImageUploadRequest $request)
{
- // create a new model instance
$category = new Category();
- // Update the category data
$category->name = $request->input('name');
$category->category_type = $request->input('category_type');
$category->eula_text = $request->input('eula_text');
diff --git a/app/Http/Controllers/CustomFieldsController.php b/app/Http/Controllers/CustomFieldsController.php
index bb2f4fa0c..790b06d39 100644
--- a/app/Http/Controllers/CustomFieldsController.php
+++ b/app/Http/Controllers/CustomFieldsController.php
@@ -1,6 +1,7 @@
$request->get("name"),
@@ -81,27 +82,19 @@ class CustomFieldsController extends Controller
]);
-
if (!in_array(Input::get('format'), array_keys(CustomField::$PredefinedFormats))) {
$field->format = e($request->get("custom_format"));
} else {
$field->format = e($request->get("format"));
}
-
- $validator = Validator::make(Input::all(), $field->rules);
-
- if ($validator->passes()) {
- $results = $field->save();
- if ($results) {
- return redirect()->route("fields.index")->with("success", trans('admin/custom_fields/message.field.create.success'));
- } else {
- dd($field);
- return redirect()->back()->withInput()->with('error', trans('admin/custom_fields/message.field.create.error'));
- }
+ if ($field->save()) {
+ return redirect()->route("fields.index")->with("success", trans('admin/custom_fields/message.field.create.success'));
} else {
- return redirect()->back()->withInput()->withErrors($validator);
+ // dd($field);
+ return redirect()->back()->withInput()->with('error', trans('admin/custom_fields/message.field.create.error'));
}
+
}
@@ -169,7 +162,7 @@ class CustomFieldsController extends Controller
* @since [v4.0]
* @return Redirect
*/
- public function update(Request $request, $id)
+ public function update(CustomFieldRequest $request, $id)
{
$field = CustomField::find($id);
@@ -186,13 +179,12 @@ class CustomFieldsController extends Controller
$field->format = e($request->get("format"));
}
- $validator = Validator::make(Input::all(), $field->rules);
if ($field->save()) {
return redirect()->route("fields.index")->with("success", trans('admin/custom_fields/message.field.update.success'));
}
- return redirect()->back()->withInput()->withErrors($validator);
+ return redirect()->back()->withInput()->with('error', trans('admin/custom_fields/message.field.update.error'));
}
diff --git a/app/Http/Requests/CustomFieldRequest.php b/app/Http/Requests/CustomFieldRequest.php
new file mode 100644
index 000000000..f1f09e40d
--- /dev/null
+++ b/app/Http/Requests/CustomFieldRequest.php
@@ -0,0 +1,31 @@
+ "required|unique:custom_fields",
+ "custom_format" => "valid_regex",
+ ];
+ }
+}
diff --git a/app/Models/CustomField.php b/app/Models/CustomField.php
index c0ddba3cc..696b0454b 100644
--- a/app/Models/CustomField.php
+++ b/app/Models/CustomField.php
@@ -25,10 +25,13 @@ class CustomField extends Model
];
public $rules = [
- "name" => "required|unique:custom_fields"
+ "name" => "required|unique:custom_fields"
];
- public static $table_name="assets";
+ // 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
+ public static $table_name = "assets";
public static function name_to_db_name($name)
{
@@ -39,7 +42,6 @@ class CustomField extends Model
{
self::created(function ($custom_field) {
-
// column exists - nothing to do here
if (Schema::hasColumn(CustomField::$table_name, $custom_field->convertUnicodeDbSlug())) {
return false;
@@ -62,14 +64,17 @@ class CustomField extends Model
return true;
}
+ // This is just a dumb thing we have to include because Laraval/Doctrine doesn't
+ // play well with enums or a table that EVER had enums. :(
$platform = Schema::getConnection()->getDoctrineSchemaManager()->getDatabasePlatform();
$platform->registerDoctrineTypeMapping('enum', 'string');
-
+
+ // Rename the field if the name has changed
Schema::table(CustomField::$table_name, function ($table) use ($custom_field) {
$table->renameColumn($custom_field->convertUnicodeDbSlug($custom_field->getOriginal("name")), $custom_field->convertUnicodeDbSlug());
});
-
+ // Save the updated column name to the custom fields table
$custom_field->db_column = $custom_field->convertUnicodeDbSlug();
$custom_field->save();
@@ -78,6 +83,8 @@ class CustomField extends Model
return true;
});
+
+ // Drop the assets column if we've deleted it from custom fields
self::deleting(function ($custom_field) {
return Schema::table(CustomField::$table_name, function ($table) use ($custom_field) {
$table->dropColumn($custom_field->convertUnicodeDbSlug());
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
index a3184e72b..d3527ee7e 100644
--- a/app/Providers/AppServiceProvider.php
+++ b/app/Providers/AppServiceProvider.php
@@ -75,6 +75,41 @@ class AppServiceProvider extends ServiceProvider
});
+
+ // Yo dawg. I heard you like validators.
+ // This validates the custom validator regex in custom fields.
+ // We're just checking that the regex won't throw an exception, not
+ // that it's actually correct for what the user intended.
+
+ Validator::extend('valid_regex', function ($attribute, $value, $parameters, $validator) {
+
+ // Make sure it's not just an ANY format
+ if ($value!='') {
+
+ // Check that the string starts with regex:
+ if (strpos($value, 'regex:') === FALSE) {
+ return false;
+ }
+
+ $test_string = 'My hovercraft is full of eels';
+
+ // We have to stip out the regex: part here to check with preg_match
+ $test_pattern = str_replace('regex:','', $value);
+
+ try {
+ preg_match($test_pattern, $test_string, $matches);
+ return true;
+ } catch (\Exception $e) {
+ return false;
+ }
+
+ }
+ return true;
+
+ });
+
+
+
// Share common setting variables with all views.
view()->composer('*', function ($view) {
$view->with('snipeSettings', \App\Models\Setting::getSettings());
diff --git a/database/migrations/2017_10_27_192423_migrate_denormed_asset_locations.php b/database/migrations/2017_10_27_192423_migrate_denormed_asset_locations.php
index d6bf0946e..2da67eb66 100644
--- a/database/migrations/2017_10_27_192423_migrate_denormed_asset_locations.php
+++ b/database/migrations/2017_10_27_192423_migrate_denormed_asset_locations.php
@@ -1,11 +1,6 @@
with('defaultLoc')->get();
- \Log::info('Unasigned assets: ');
- foreach ($rtd_assets as $rtd_asset) {
- \Log::info('Setting asset '.$rtd_asset->id.' to location: '.$rtd_asset->rtd_location_id." Because asset's default location is: ".$rtd_asset->rtd_location_id);
- $rtd_asset->location_id=$rtd_asset->rtd_location_id;
- $rtd_asset->unsetEventDispatcher();
- $rtd_asset->save();
- }
-
- // Assigned to users - ::with('assignedTo') //can't eager-load polymorphic relations?
- $assigned_user_assets = Asset::where('assigned_type',User::class)->whereNotNull('assigned_to')->get();
- \Log::debug('User-assigned assets:');
- foreach ($assigned_user_assets as $assigned_user_asset) {
- if (($assigned_user_asset->assignedTo) && ($assigned_user_asset->assignedTo->userLoc)) {
- $new_location=$assigned_user_asset->assignedTo->userloc->id;
- \Log::info(' They are in '.$assigned_user_asset->assignedTo->userloc->name.' which is id: '.$new_location);
- } else {
- \Log::info('They have no location! ');
- $new_location=$assigned_user_asset->rtd_location_id;
- }
- $assigned_user_asset->location_id=$new_location;
- $assigned_user_asset->unsetEventDispatcher();
- $assigned_user_asset->save();
-
- }
-
- // Assigned to locations // with('assetloc')-> //can't eager-load polymorphic relationships
- $assigned_location_assets = Asset::where('assigned_type',Location::class)->whereNotNull('assigned_to')->get();
- \Log::info('Location-assigned assets: ');
- foreach ($assigned_location_assets as $assigned_location_asset) {
- $assigned_location_asset->location_id=$assigned_location_asset->assignedTo->id;
- \Log::info('(calculated to be: '.$assigned_location_asset->assetLoc());
- $assigned_location_asset->unsetEventDispatcher();
- $assigned_location_asset->save();
- }
-
- // Assigned to assets
- $assigned_asset_assets = Asset::where('assigned_type',Asset::class)->whereNotNull('assigned_to')->with('assetloc')->get();
- \Log::info('Asset-assigned assets: ');
- foreach ($assigned_asset_assets as $assigned_asset_asset) {
- \Log::info('This asset is: '.$assigned_asset_asset->assignedTo->asset_tag);
- if (($assigned_asset_asset->assignedTo) && ($assigned_asset_asset->assignedTo->location)) {
- \Log::info('They are in '.$assigned_asset_asset->assignedTo->location->name);
- }
- if ($assigned_asset_asset->assetloc) {
- \Log::info('User location is: '.$assigned_asset_asset->assetloc->name);
- \Log::info('Setting asset '.$assigned_asset_asset->id.' location to '.$assigned_asset_asset->assetloc->id.' ('.$assigned_asset_asset->assetloc->name.')');
- $assigned_asset_asset->location_id=$assigned_asset_asset->assetloc->id;
- }
-
-
-
- }
-
- $unassigned_assets=Asset::whereNull("location_id")->get();
- foreach($unassigned_assets as $unassigned_asset) {
- \Log::info('Asset: '.$unassigned_asset->id.' still has no location');
- }
-
- $assets = Asset::get();
-
- foreach ($assets as $asset) {
- if (($asset) && ($asset->assetLoc()) && ($asset->location_id != $asset->assetLoc()->id)) {
- \Log::info('MISMATCH MISMATCH '.$asset->id. "doesn't match its location");
- }
- }
-
-
-
+ // the contents of this migration have moved to the `php artisan snipeit:sync-asset-locations` script
+ // I know its gross to edit a migration, but we had to do this for support purposes. - @snipe
+ Artisan::call('snipeit:sync-asset-locations', ['--output' => 'all']);
+ $output = Artisan::output();
+ \Log::info($output);
}
/**
diff --git a/resources/lang/en/admin/custom_fields/general.php b/resources/lang/en/admin/custom_fields/general.php
index f2e6df90c..564a9617d 100644
--- a/resources/lang/en/admin/custom_fields/general.php
+++ b/resources/lang/en/admin/custom_fields/general.php
@@ -5,7 +5,7 @@ return array(
'field' => 'Field',
'about_fieldsets_title' => 'About Fieldsets',
'about_fieldsets_text' => 'Fieldsets allow you to create groups of custom fields that are frequently re-used used for specific asset model types.',
- 'custom_format' => 'Custom format...',
+ 'custom_format' => 'Custom regex format...',
'encrypt_field' => 'Encrypt the value of this field in the database',
'encrypt_field_help' => 'WARNING: Encrypting a field makes it unsearchable.',
'encrypted' => 'Encrypted',
@@ -19,7 +19,8 @@ return array(
'field_element' => 'Form Element',
'field_element_short' => 'Element',
'field_format' => 'Format',
- 'field_custom_format' => 'Custom Format',
+ 'field_custom_format' => 'Custom Regex Format',
+ 'field_custom_format_help' => 'This field allows you to use a regex expression for validation. It should start with "regex:" - for example, to validate that a custom field value contains a valid IMEI (15 numeric digits), you would use regex:/^[0-9]{15}$/
.',
'required' => 'Required',
'req' => 'Req.',
'used_by_models' => 'Used By Models',
diff --git a/resources/lang/en/validation.php b/resources/lang/en/validation.php
index ee4ecbda4..23116776e 100644
--- a/resources/lang/en/validation.php
+++ b/resources/lang/en/validation.php
@@ -67,6 +67,7 @@ return array(
'not_in' => 'The selected :attribute is invalid.',
'numeric' => 'The :attribute must be a number.',
'present' => 'The :attribute field must be present.',
+ 'valid_regex' => 'That is not a valid regex. ',
'regex' => 'The :attribute format is invalid.',
'required' => 'The :attribute field is required.',
'required_if' => 'The :attribute field is required when :other is :value.',
diff --git a/resources/views/custom_fields/fields/edit.blade.php b/resources/views/custom_fields/fields/edit.blade.php
index 2709aaf9a..918545de7 100644
--- a/resources/views/custom_fields/fields/edit.blade.php
+++ b/resources/views/custom_fields/fields/edit.blade.php
@@ -82,7 +82,9 @@
{{ trans('admin/custom_fields/general.field_custom_format') }}
{!! trans('admin/custom_fields/general.field_custom_format_help') !!}
+ {!! $errors->first('custom_format', ' :message') !!}