Merge pull request #13882 from marcusmoore/fixes/jquery-validation

Fix client side validation in the v7 branch
This commit is contained in:
snipe 2023-12-05 17:26:48 +00:00 committed by GitHub
commit 0089ea2321
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 65 additions and 23 deletions

View file

@ -421,6 +421,7 @@ class SettingsController extends Controller
// Only allow the site name and CSS to be changed if lock_passwords is false
// Because public demos make people act like dicks
if (! config('app.lock_passwords')) {
$request->validate(['site_name' => 'required']);
$setting->site_name = $request->input('site_name');
$setting->custom_css = $request->input('custom_css');
}

9
package-lock.json generated
View file

@ -25,6 +25,7 @@
"jquery-slimscroll": "^1.3.8",
"jquery-ui": "^1.13.2",
"jquery-ui-bundle": "^1.12.1",
"jquery-validation": "^1.20.0",
"jquery.iframe-transport": "^1.0.0",
"jspdf-autotable": "^3.7.1",
"less": "^4.2.0",
@ -7087,6 +7088,14 @@
"version": "1.12.1",
"license": "MIT"
},
"node_modules/jquery-validation": {
"version": "1.20.0",
"resolved": "https://registry.npmjs.org/jquery-validation/-/jquery-validation-1.20.0.tgz",
"integrity": "sha512-c8tg4ltIIP6L7l0bZ79sRzOJYquyjS48kQZ6iv8MJ2r0OYztxtkWYKTReZyU2/zVFYiINB29i0Z/IRNNuJQN1g==",
"peerDependencies": {
"jquery": "^1.7 || ^2.0 || ^3.1"
}
},
"node_modules/jquery.iframe-transport": {
"version": "1.0.0",
"license": "MIT"

View file

@ -44,6 +44,7 @@
"jquery-slimscroll": "^1.3.8",
"jquery-ui": "^1.13.2",
"jquery-ui-bundle": "^1.12.1",
"jquery-validation": "^1.20.0",
"jquery.iframe-transport": "^1.0.0",
"jspdf-autotable": "^3.7.1",
"less": "^4.2.0",

View file

@ -17,7 +17,7 @@
</label>
<div class="col-md-7 col-sm-12 {{ (Helper::checkIfRequired($item, 'months')) ? ' required' : '' }}">
<div class="col-md-7" style="padding-left:0px">
<input class="form-control" type="text" name="months" id="months" value="{{ Request::old('months', $item->months) }}" style="width: 80px;"{!! (\App\Helpers\Helper::checkIfRequired($item, 'months')) ? ' data-validation="required" required' : '' !!} />
<input class="form-control" type="text" name="months" id="months" value="{{ Request::old('months', $item->months) }}" style="width: 80px;"{!! (\App\Helpers\Helper::checkIfRequired($item, 'months')) ? ' required' : '' !!} />
{!! $errors->first('months', '<span class="alert-msg" aria-hidden="true"><i class="fa fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>
</div>

View file

@ -26,14 +26,14 @@
<div class="col-md-7 col-sm-12{{ (Helper::checkIfRequired($item, 'asset_tag')) ? ' required' : '' }}">
<input class="form-control" type="text" name="asset_tags[1]" id="asset_tag" value="{{ old('asset_tag', $item->asset_tag) }}" data-validation="required">
<input class="form-control" type="text" name="asset_tags[1]" id="asset_tag" value="{{ old('asset_tag', $item->asset_tag) }}" required>
{!! $errors->first('asset_tags', '<span class="alert-msg"><i class="fas fa-times"></i> :message</span>') !!}
{!! $errors->first('asset_tag', '<span class="alert-msg"><i class="fas fa-times"></i> :message</span>') !!}
</div>
@else
<!-- we are creating a new asset - let people use more than one asset tag -->
<div class="col-md-7 col-sm-12{{ (Helper::checkIfRequired($item, 'asset_tag')) ? ' required' : '' }}">
<input class="form-control" type="text" name="asset_tags[1]" id="asset_tag" value="{{ old('asset_tags.1', \App\Models\Asset::autoincrement_asset()) }}" data-validation="required">
<input class="form-control" type="text" name="asset_tags[1]" id="asset_tag" value="{{ old('asset_tags.1', \App\Models\Asset::autoincrement_asset()) }}" required>
{!! $errors->first('asset_tags', '<span class="alert-msg"><i class="fas fa-times"></i> :message</span>') !!}
{!! $errors->first('asset_tag', '<span class="alert-msg"><i class="fas fa-times"></i> :message</span>') !!}
</div>
@ -295,7 +295,7 @@
box_html += '<span class="fields_wrapper">';
box_html += '<div class="form-group"><label for="asset_tag" class="col-md-3 control-label">{{ trans('admin/hardware/form.tag') }} ' + x + '</label>';
box_html += '<div class="col-md-7 col-sm-12 required">';
box_html += '<input type="text" class="form-control" name="asset_tags[' + x + ']" value="{{ (($snipeSettings->auto_increment_prefix!='') && ($snipeSettings->auto_increment_assets=='1')) ? $snipeSettings->auto_increment_prefix : '' }}'+ auto_tag +'" data-validation="required">';
box_html += '<input type="text" class="form-control" name="asset_tags[' + x + ']" value="{{ (($snipeSettings->auto_increment_prefix!='') && ($snipeSettings->auto_increment_assets=='1')) ? $snipeSettings->auto_increment_prefix : '' }}'+ auto_tag +'" required>';
box_html += '</div>';
box_html += '<div class="col-md-2 col-sm-12">';
box_html += '<a href="#" class="remove_field btn btn-default btn-sm"><i class="fas fa-minus"></i></a>';

View file

@ -965,13 +965,25 @@
$('.js-copy-link').tooltip('hide').attr('data-original-title', '{{ trans('general.copied') }}').tooltip('show');
});
// ignore: 'input[type=hidden]' is required here to validate the select2 lists
$.validate({
form: '#create-form',
modules: 'date, toggleDisabled',
disabledFormFilter: '#create-form',
showErrorDialogs: true,
ignore: 'input[type=hidden]'
// Reference: https://jqueryvalidation.org/validate/
$('#create-form').validate({
ignore: 'input[type=hidden]',
errorClass: 'help-block form-error',
errorElement: 'span',
errorPlacement: function(error, element) {
$(element).hasClass('select2') || $(element).hasClass('js-data-ajax')
// If the element is a select2 then place the error above the input
? element.parents('.required').append(error)
// Otherwise place it after
: error.insertAfter(element);
},
highlight: function(inputElement) {
$(inputElement).parent().addClass('has-error');
$(inputElement).closest('.help-block').remove();
},
onfocusout: function(element) {
return $(element).valid();
},
});

View file

@ -4,7 +4,7 @@
{{ Form::label($fieldname, $translated_name, array('class' => 'col-md-3 control-label')) }}
<div class="col-md-7{{ (isset($item) && (Helper::checkIfRequired($item, $fieldname))) ? ' required' : '' }}">
<select class="js-data-ajax" data-endpoint="categories/{{ (isset($category_type)) ? $category_type : 'assets' }}" data-placeholder="{{ trans('general.select_category') }}" name="{{ $fieldname }}" style="width: 100%" id="category_select_id" aria-label="{{ $fieldname }}" {!! ((isset($item)) && (Helper::checkIfRequired($item, $fieldname))) ? ' data-validation="required" required' : '' !!}{{ (isset($multiple) && ($multiple=='true')) ? " multiple='multiple'" : '' }}>
<select class="js-data-ajax" data-endpoint="categories/{{ (isset($category_type)) ? $category_type : 'assets' }}" data-placeholder="{{ trans('general.select_category') }}" name="{{ $fieldname }}" style="width: 100%" id="category_select_id" aria-label="{{ $fieldname }}" {!! ((isset($item)) && (Helper::checkIfRequired($item, $fieldname))) ? ' required ' : '' !!}{{ (isset($multiple) && ($multiple=='true')) ? " multiple='multiple'" : '' }}>
@if ($category_id = old($fieldname, (isset($item)) ? $item->{$fieldname} : ''))
<option value="{{ $category_id }}" selected="selected" role="option" aria-selected="true" role="option">
{{ (\App\Models\Category::find($category_id)) ? \App\Models\Category::find($category_id)->name : '' }}

View file

@ -3,7 +3,7 @@
{{ Form::label($fieldname, $translated_name, array('class' => 'col-md-3 control-label')) }}
<div class="col-md-7{{ ((isset($required) && ($required =='true'))) ? ' required' : '' }}">
<select class="js-data-ajax" data-endpoint="locations" data-placeholder="{{ trans('general.select_location') }}" name="{{ $fieldname }}" style="width: 100%" id="{{ $fieldname }}_location_select" aria-label="{{ $fieldname }}" {!! ((isset($item)) && (Helper::checkIfRequired($item, $fieldname))) ? ' data-validation="required" required' : '' !!}{{ (isset($multiple) && ($multiple=='true')) ? " multiple='multiple'" : '' }}>
<select class="js-data-ajax" data-endpoint="locations" data-placeholder="{{ trans('general.select_location') }}" name="{{ $fieldname }}" style="width: 100%" id="{{ $fieldname }}_location_select" aria-label="{{ $fieldname }}" {!! ((isset($item)) && (Helper::checkIfRequired($item, $fieldname))) ? ' required ' : '' !!}{{ (isset($multiple) && ($multiple=='true')) ? " multiple='multiple'" : '' }}>
@if ($location_id = old($fieldname, (isset($item)) ? $item->{$fieldname} : ''))
<option value="{{ $location_id }}" selected="selected" role="option" aria-selected="true" role="option">
{{ (\App\Models\Location::find($location_id)) ? \App\Models\Location::find($location_id)->name : '' }}

View file

@ -4,7 +4,7 @@
{{ Form::label($fieldname, $translated_name, array('class' => 'col-md-3 control-label')) }}
<div class="col-md-7{{ ((isset($required)) && ($required=='true')) ? ' required' : '' }}">
<select class="js-data-ajax" data-endpoint="manufacturers" data-placeholder="{{ trans('general.select_manufacturer') }}" name="{{ $fieldname }}" style="width: 100%" id="manufacturer_select_id" aria-label="{{ $fieldname }}" {!! ((isset($item)) && (Helper::checkIfRequired($item, $fieldname))) ? ' data-validation="required" required' : '' !!}{{ (isset($multiple) && ($multiple=='true')) ? " multiple='multiple'" : '' }}>
<select class="js-data-ajax" data-endpoint="manufacturers" data-placeholder="{{ trans('general.select_manufacturer') }}" name="{{ $fieldname }}" style="width: 100%" id="manufacturer_select_id" aria-label="{{ $fieldname }}" {!! ((isset($item)) && (Helper::checkIfRequired($item, $fieldname))) ? ' required ' : '' !!}{{ (isset($multiple) && ($multiple=='true')) ? " multiple='multiple'" : '' }}>
@if ($manufacturer_id = old($fieldname, (isset($item)) ? $item->{$fieldname} : ''))
<option value="{{ $manufacturer_id }}" selected="selected" role="option" aria-selected="true" role="option">
{{ (\App\Models\Manufacturer::find($manufacturer_id)) ? \App\Models\Manufacturer::find($manufacturer_id)->name : '' }}

View file

@ -4,7 +4,7 @@
{{ Form::label($fieldname, $translated_name, array('class' => 'col-md-3 control-label')) }}
<div class="col-md-7{{ ((isset($field_req)) || ((isset($required) && ($required =='true')))) ? ' required' : '' }}">
<select class="js-data-ajax" data-endpoint="models" data-placeholder="{{ trans('general.select_model') }}" name="{{ $fieldname }}" style="width: 100%" id="model_select_id" aria-label="{{ $fieldname }}"{!! (isset($field_req) ? ' data-validation="required" required' : '') !!}{{ (isset($multiple) && ($multiple=='true')) ? " multiple='multiple'" : '' }}>
<select class="js-data-ajax" data-endpoint="models" data-placeholder="{{ trans('general.select_model') }}" name="{{ $fieldname }}" style="width: 100%" id="model_select_id" aria-label="{{ $fieldname }}"{!! (isset($field_req) ? ' required ' : '') !!}{{ (isset($multiple) && ($multiple=='true')) ? " multiple='multiple'" : '' }}>
@if ($model_id = old($fieldname, ($item->{$fieldname} ?? request($fieldname) ?? '')))
<option value="{{ $model_id }}" selected="selected">
{{ (\App\Models\AssetModel::find($model_id)) ? \App\Models\AssetModel::find($model_id)->name : '' }}

View file

@ -2,7 +2,7 @@
<div class="form-group {{ $errors->has('name') ? ' has-error' : '' }}">
<label for="name" class="col-md-3 control-label">{{ $translated_name }}</label>
<div class="col-md-7 col-sm-12{{ (Helper::checkIfRequired($item, 'name')) ? ' required' : '' }}">
<input class="form-control" type="text" name="name" aria-label="name" id="name" value="{{ old('name', $item->name) }}"{!! (Helper::checkIfRequired($item, 'name')) ? ' data-validation="required" required' : '' !!} />
<input class="form-control" type="text" name="name" aria-label="name" id="name" value="{{ old('name', $item->name) }}"{!! (Helper::checkIfRequired($item, 'name')) ? ' required' : '' !!} />
{!! $errors->first('name', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>
</div>

View file

@ -4,7 +4,7 @@
<label for="qty" class="col-md-3 control-label">{{ trans('general.quantity') }}</label>
<div class="col-md-7{{ (Helper::checkIfRequired($item, 'qty')) ? ' required' : '' }}">
<div class="col-md-3" style="padding-left:0px">
<input class="form-control" type="text" name="qty" aria-label="qty" id="qty" value="{{ old('qty', $item->qty) }}" {!! (Helper::checkIfRequired($item, 'qty')) ? ' data-validation="required" required' : '' !!}/>
<input class="form-control" type="text" name="qty" aria-label="qty" id="qty" value="{{ old('qty', $item->qty) }}" {!! (Helper::checkIfRequired($item, 'qty')) ? ' required ' : '' !!}/>
</div>
{!! $errors->first('qty', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>

View file

@ -4,7 +4,7 @@
{{ Form::label($fieldname, $translated_name, array('class' => 'col-md-3 control-label')) }}
<div class="col-md-7{{ ((isset($required)) && ($required=='true')) ? ' required' : '' }}">
<select class="js-data-ajax" data-endpoint="statuslabels" data-placeholder="{{ trans('general.select_statuslabel') }}" name="{{ $fieldname }}" style="width: 100%" id="status_select_id" aria-label="{{ $fieldname }}" {!! ((isset($item)) && (Helper::checkIfRequired($item, $fieldname))) ? ' data-validation="required" required' : '' !!}{{ (isset($multiple) && ($multiple=='true')) ? " multiple='multiple'" : '' }}>
<select class="js-data-ajax" data-endpoint="statuslabels" data-placeholder="{{ trans('general.select_statuslabel') }}" name="{{ $fieldname }}" style="width: 100%" id="status_select_id" aria-label="{{ $fieldname }}" {!! ((isset($item)) && (Helper::checkIfRequired($item, $fieldname))) ? ' required ' : '' !!}{{ (isset($multiple) && ($multiple=='true')) ? " multiple='multiple'" : '' }}>
@if ($status_id = old($fieldname, (isset($item)) ? $item->{$fieldname} : ''))
<option value="{{ $status_id }}" selected="selected" role="option" aria-selected="true" role="option">
{{ (\App\Models\Statuslabel::find($status_id)) ? \App\Models\Statuslabel::find($status_id)->name : '' }}

View file

@ -2,7 +2,7 @@
<div class="form-group {{ $errors->has('status_id') ? ' has-error' : '' }}">
<label for="status_id" class="col-md-3 control-label">{{ trans('admin/hardware/form.status') }}</label>
<div class="col-md-7 col-sm-11{{ (Helper::checkIfRequired($item, 'status_id')) ? ' required' : '' }}">
{{ Form::select('status_id', $statuslabel_list , old('status_id', $item->status_id), array('class'=>'select2 status_id', 'style'=>'width:100%','id'=>'status_select_id', 'aria-label'=>'status_id', 'data-validation' => "required")) }}
{{ Form::select('status_id', $statuslabel_list , old('status_id', $item->status_id), array('class'=>'select2 status_id', 'style'=>'width:100%','id'=>'status_select_id', 'aria-label'=>'status_id', 'required' => 'required')) }}
{!! $errors->first('status_id', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>
<div class="col-md-2 col-sm-2 text-left">

View file

@ -52,7 +52,7 @@
<p class="text-warning"><i class="fas fa-lock"></i> {{ trans('general.feature_disabled') }}</p>
@else
{{ Form::text('site_name',
Request::old('site_name', $setting->site_name), array('class' => 'form-control','placeholder' => 'Snipe-IT Asset Management', 'data-validation' => 'required')) }}
Request::old('site_name', $setting->site_name), array('class' => 'form-control','placeholder' => 'Snipe-IT Asset Management', 'required' => 'required')) }}
@endif
{!! $errors->first('site_name', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
</div>

View file

@ -0,0 +1,19 @@
<?php
namespace Tests\Feature\Settings;
use App\Models\User;
use Tests\Support\InteractsWithSettings;
use Tests\TestCase;
class BrandingSettingsTest extends TestCase
{
use InteractsWithSettings;
public function testSiteNameIsRequired()
{
$this->actingAs(User::factory()->superuser()->create())
->post(route('settings.branding.save', ['site_name' => '']))
->assertInvalid('site_name');
}
}

View file

@ -154,7 +154,7 @@ mix.combine(
"./resources/assets/js/extensions/pGenerator.jquery.js",
"./node_modules/chart.js/dist/Chart.js",
"./resources/assets/js/signature_pad.js",
//"./node_modules/jquery-form-validator/form-validator/jquery.form-validator.js", //problem?
"./node_modules/jquery-validation/dist/jquery.validate.js",
"./node_modules/list.js/dist/list.js",
"./node_modules/clipboard/dist/clipboard.js",
],