Fixed: #5896 Custom fields of type "CUSTOM REGEX" are always saved as "ANY" (#6381)

* Fixed missing oauth tables during setup.

* Custom fields of type "CUSTOM REGEX" are always saved as "ANY" 

Fixes #5896

* Updated per PR

Fixed spelling

* Fixed logic error

Moved conditional code from view to controller
Added getFromatType function for dropdown
This commit is contained in:
Wes Hulette 2018-12-06 23:05:04 -05:00 committed by snipe
parent 886b6dd265
commit b38d07064b
6 changed files with 102 additions and 71 deletions

View file

@ -225,8 +225,9 @@ class Helper
*/ */
public static function predefined_formats() public static function predefined_formats()
{ {
$keys = array_keys(CustomField::$PredefinedFormats); $keys = array_keys(CustomField::PREDEFINED_FORMATS);
$stuff = array_combine($keys, $keys); $stuff = array_combine($keys, $keys);
return $stuff; return $stuff;
} }

View file

@ -1,12 +1,13 @@
<?php <?php
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Http\Requests\CustomFieldRequest;
use App\Models\CustomFieldset;
use App\Models\CustomField;
use Illuminate\Support\Facades\Input;
use Redirect; use Redirect;
use App\Helpers\Helper;
use App\Models\CustomField;
use App\Models\CustomFieldset;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Input;
use App\Http\Requests\CustomFieldRequest;
/** /**
@ -36,6 +37,7 @@ class CustomFieldsController extends Controller
$fieldsets = CustomFieldset::with("fields", "models")->get(); $fieldsets = CustomFieldset::with("fields", "models")->get();
$fields = CustomField::with("fieldset")->get(); $fields = CustomField::with("fieldset")->get();
return view("custom_fields.index")->with("custom_fieldsets", $fieldsets)->with("custom_fields", $fields); return view("custom_fields.index")->with("custom_fieldsets", $fieldsets)->with("custom_fields", $fields);
} }
@ -53,7 +55,9 @@ class CustomFieldsController extends Controller
{ {
$this->authorize('create', CustomField::class); $this->authorize('create', CustomField::class);
return view("custom_fields.fields.edit")->with('field', new CustomField()); return view("custom_fields.fields.edit",[
'predefinedFormats' => Helper::predefined_formats()
])->with('field', new CustomField());
} }
@ -158,7 +162,16 @@ class CustomFieldsController extends Controller
$this->authorize('update', $field); $this->authorize('update', $field);
return view("custom_fields.fields.edit")->with('field', $field); $customFormat = '';
if((stripos($field->format, 'regex') === 0) && ($field->format !== CustomField::PREDEFINED_FORMATS['MAC'])) {
$customFormat = $field->format;
}
return view("custom_fields.fields.edit",[
'field' => $field,
'customFormat' => $customFormat,
'predefinedFormats' => Helper::predefined_formats()
]);
} }
@ -176,17 +189,17 @@ class CustomFieldsController extends Controller
public function update(CustomFieldRequest $request, $id) public function update(CustomFieldRequest $request, $id)
{ {
$field = CustomField::find($id); $field = CustomField::find($id);
$this->authorize('update', $field); $this->authorize('update', $field);
$field->name = e($request->get("name")); $field->name = e($request->get("name"));
$field->element = e($request->get("element")); $field->element = e($request->get("element"));
$field->field_values = e($request->get("field_values")); $field->field_values = e($request->get("field_values"));
$field->user_id = Auth::id(); $field->user_id = Auth::id();
$field->help_text = $request->get("help_text"); $field->help_text = $request->get("help_text");
$field->show_in_email = $request->get("show_in_email", 0); $field->show_in_email = $request->get("show_in_email", 0);
if (!in_array(Input::get('format'), array_keys(CustomField::$PredefinedFormats))) { if ($request->get('format') == 'CUSTOM REGEX') {
$field->format = e($request->get("custom_format")); $field->format = e($request->get("custom_format"));
} else { } else {
$field->format = e($request->get("format")); $field->format = e($request->get("format"));

View file

@ -15,27 +15,32 @@ class CustomField extends Model
use ValidatingTrait, use ValidatingTrait,
UniqueUndeletedTrait; UniqueUndeletedTrait;
/**
* Custom field predfined formats
*
* @var array
*/
const PREDEFINED_FORMATS = [
'ANY' => '',
'CUSTOM REGEX' => '',
'ALPHA' => 'alpha',
'ALPHA-DASH' => 'alpha_dash',
'NUMERIC' => 'numeric',
'ALPHA-NUMERIC' => 'alpha_num',
'EMAIL' => 'email',
'DATE' => 'date',
'URL' => 'url',
'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 $guarded = [ public $guarded = [
"id" "id"
]; ];
public static $PredefinedFormats = [
"ANY" => "",
"CUSTOM REGEX" => "",
"ALPHA" => "alpha",
"ALPHA-DASH" => "alpha_dash",
"NUMERIC" => "numeric",
"ALPHA-NUMERIC" => "alpha_num",
"EMAIL" => "email",
"DATE" => "date",
"URL" => "url",
"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",
];
/** /**
* Validation rules. * Validation rules.
* At least empty array must be provided if using ValidatingTrait. * At least empty array must be provided if using ValidatingTrait.
@ -248,11 +253,12 @@ class CustomField extends Model
*/ */
public function getFormatAttribute($value) public function getFormatAttribute($value)
{ {
foreach (self::$PredefinedFormats as $name => $pattern) { foreach (self::PREDEFINED_FORMATS as $name => $pattern) {
if ($pattern === $value || $name === $value) { if ($pattern === $value || $name === $value) {
return $name; return $name;
} }
} }
return $value; return $value;
} }
@ -265,8 +271,8 @@ class CustomField extends Model
*/ */
public function setFormatAttribute($value) public function setFormatAttribute($value)
{ {
if (isset(self::$PredefinedFormats[$value])) { if (isset(self::PREDEFINED_FORMATS[$value])) {
$this->attributes['format']=self::$PredefinedFormats[$value]; $this->attributes['format']=self::PREDEFINED_FORMATS[$value];
} else { } else {
$this->attributes['format']=$value; $this->attributes['format']=$value;
} }
@ -354,9 +360,28 @@ class CustomField extends Model
Rule::in(['text', 'listbox']) Rule::in(['text', 'listbox'])
], ],
'format' => [ 'format' => [
Rule::in(array_merge(array_keys(CustomField::$PredefinedFormats), CustomField::$PredefinedFormats)) Rule::in(array_merge(array_keys(CustomField::PREDEFINED_FORMATS), CustomField::PREDEFINED_FORMATS))
], ],
'field_encrypted' => "nullable|boolean" 'field_encrypted' => "nullable|boolean"
]; ];
} }
/**
* Check to see if there is a custom regex format type
* @see https://github.com/snipe/snipe-it/issues/5896
*
* @author Wes Hulette <jwhulette@gmail.com>
*
* @since 5.0.0
*
* @return string
*/
public function getFormatType()
{
if(stripos($this->format,'regex') === 0 && ($this->format !== self::PREDEFINED_FORMATS['MAC'])) {
return 'CUSTOM REGEX';
}
return $this->format;
}
} }

View file

@ -21,7 +21,7 @@ class MigrateMacAddress extends Migration {
} }
$macid=DB::table('custom_fields')->insertGetId([ $macid=DB::table('custom_fields')->insertGetId([
'name' => "MAC Address", 'name' => "MAC Address",
'format' => \App\Models\CustomField::$PredefinedFormats['MAC'], 'format' => \App\Models\CustomField::PREDEFINED_FORMATS['MAC'],
'element'=>'text']); 'element'=>'text']);
if(!$macid) { if(!$macid) {
throw new Exception("Can't save MAC Custom field: $macid"); throw new Exception("Can't save MAC Custom field: $macid");

View file

@ -1,4 +1,9 @@
@php
use App\Models\CustomField;
@endphp
@extends('layouts/default') @extends('layouts/default')
{{-- Page title --}} {{-- Page title --}}
@section('title') @section('title')
{{ trans('admin/custom_fields/general.custom_fields') }} {{ trans('admin/custom_fields/general.custom_fields') }}
@ -70,19 +75,18 @@
{{ trans('admin/custom_fields/general.field_format') }} {{ trans('admin/custom_fields/general.field_format') }}
</label> </label>
<div class="col-md-6 required"> <div class="col-md-6 required">
{{ Form::select("format",\App\Helpers\Helper::predefined_formats(), $field->format, array('class'=>'format select2 form-control')) }} {{ Form::select("format",$predefinedFormats, $field->getFormatType(),
array('class'=>'format select2 form-control')) }}
{!! $errors->first('format', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!} {!! $errors->first('format', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
</div> </div>
</div> </div>
<!-- Custom Format --> <!-- Custom Format -->
<div class="form-group {{ $errors->has('custom_format') ? ' has-error' : '' }}" id="custom_regex" style="display:none;"> <div class="form-group {{ $errors->has('custom_format') ? ' has-error' : '' }}" id="custom_regex" style="display:none;">
<label for="custom_format" class="col-md-4 control-label"> <label for="custom_format" class="col-md-4 control-label">
{{ trans('admin/custom_fields/general.field_custom_format') }} {{ trans('admin/custom_fields/general.field_custom_format') }}
</label> </label>
<div class="col-md-6 required"> <div class="col-md-6 required">
{{ Form::text('custom_format', Input::old('custom_format', $customFormat), 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}$/')) }}
<p class="help-block">{!! trans('admin/custom_fields/general.field_custom_format_help') !!}</p> <p class="help-block">{!! trans('admin/custom_fields/general.field_custom_format_help') !!}</p>
{!! $errors->first('custom_format', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!} {!! $errors->first('custom_format', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
@ -115,55 +119,45 @@
@if (!$field->id) @if (!$field->id)
<!-- Encrypted -->
<div class="form-group {{ $errors->has('encrypted') ? ' has-error' : '' }}">
<div class="col-md-8 col-md-offset-4">
<label for="field_encrypted">
<input type="checkbox" value="1" name="field_encrypted" id="field_encrypted" class="minimal"{{ (Input::old('field_encrypted') || $field->field_encrypted) ? ' checked="checked"' : '' }}>
{{ trans('admin/custom_fields/general.encrypt_field') }}
</label>
</div>
<div class="col-md-6 col-md-offset-4" id="encrypt_warning" style="display:none;">
<div class="callout callout-danger">
<p><i class="fa fa-warning"></i> {{ trans('admin/custom_fields/general.encrypt_field_help') }}</p>
<!-- Encrypted -->
<div class="form-group {{ $errors->has('encrypted') ? ' has-error' : '' }}">
<div class="col-md-8 col-md-offset-4">
<label for="field_encrypted">
<input type="checkbox" value="1" name="field_encrypted" id="field_encrypted" class="minimal"{{ (Input::old('field_encrypted') || $field->field_encrypted) ? ' checked="checked"' : '' }}>
{{ trans('admin/custom_fields/general.encrypt_field') }}
</label>
</div>
<div class="col-md-6 col-md-offset-4" id="encrypt_warning" style="display:none;">
<div class="callout callout-danger">
<p><i class="fa fa-warning"></i> {{ trans('admin/custom_fields/general.encrypt_field_help') }}</p>
</div>
</div> </div>
</div> </div>
@endif </div>
@endif
</div> <!-- /.box-body--> </div> <!-- /.box-body-->
<div class="box-footer text-right"> <div class="box-footer text-right">
<button type="submit" class="btn btn-success"> {{ trans('general.save') }}</button> <button type="submit" class="btn btn-success"> {{ trans('general.save') }}</button>
</div> </div>
</div> <!--.box.box-default--> </div> <!--.box.box-default-->
{{ Form::close() }} {{ Form::close() }}
</div> <!--/.col-md-9--> </div> <!--/.col-md-9-->
<div class="col-md-3"> <div class="col-md-3">
<h4>About Custom Fields</h4> <h4>About Custom Fields</h4>
<p>Custom fields allow you to add arbitrary attributes to assets.</p> <p>Custom fields allow you to add arbitrary attributes to assets.</p>
</div> </div>
</div> </div>
@stop @stop
@section('moar_scripts') @section('moar_scripts')
<script nonce="{{ csrf_token() }}"> <script nonce="{{ csrf_token() }}">
$(document).ready(function(){ $(document).ready(function(){
// Initialize selected index of the format dropdown
// 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);
}
// Only display the custom format field if it's a custom format validation type // Only display the custom format field if it's a custom format validation type
$(".format").change(function(){ $(".format").change(function(){
$(this).find("option:selected").each(function(){ $(this).find("option:selected").each(function(){
@ -187,8 +181,6 @@
}).change(); }).change();
}); });
// Checkbox handling // Checkbox handling
$('#field_encrypted').on('ifChecked', function(event){ $('#field_encrypted').on('ifChecked', function(event){
$("#encrypt_warning").show(); $("#encrypt_warning").show();

View file

@ -27,7 +27,7 @@ class CustomFieldTest extends BaseTest
'element' => $customfield->element, 'element' => $customfield->element,
]; ];
$this->assertEquals($customfield->getAttributes()['format'], CustomField::$PredefinedFormats['IP']); //this seems undocumented... $this->assertEquals($customfield->getAttributes()['format'], CustomField::PREDEFINED_FORMATS['IP']); //this seems undocumented...
$this->assertEquals($customfield->format, "IP"); $this->assertEquals($customfield->format, "IP");
} }