mirror of
https://github.com/snipe/snipe-it.git
synced 2024-11-10 23:54:12 -08:00
Merge remote-tracking branch 'origin/develop'
This commit is contained in:
commit
a48eb60f87
|
@ -18,7 +18,7 @@ class LdapSync extends Command
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $signature = 'snipeit:ldap-sync {--location=} {--location_id=} {--base_dn=} {--filter=} {--summary} {--json_summary}';
|
protected $signature = 'snipeit:ldap-sync {--location=} {--location_id=*} {--base_dn=} {--filter=} {--summary} {--json_summary}';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The console command description.
|
* The console command description.
|
||||||
|
@ -84,10 +84,13 @@ class LdapSync extends Command
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ( $this->option('location_id') != '') {
|
if ( $this->option('location_id') != '') {
|
||||||
$location_ou= Location::where('id', '=', $this->option('location_id'))->value('ldap_ou');
|
|
||||||
|
foreach($this->option('location_id') as $location_id){
|
||||||
|
$location_ou= Location::where('id', '=', $location_id)->value('ldap_ou');
|
||||||
$search_base = $location_ou;
|
$search_base = $location_ou;
|
||||||
Log::debug('Importing users from specified location OU: \"'.$search_base.'\".');
|
Log::debug('Importing users from specified location OU: \"'.$search_base.'\".');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if ($this->option('base_dn') != '') {
|
else if ($this->option('base_dn') != '') {
|
||||||
$search_base = $this->option('base_dn');
|
$search_base = $this->option('base_dn');
|
||||||
Log::debug('Importing users from specified base DN: \"'.$search_base.'\".');
|
Log::debug('Importing users from specified base DN: \"'.$search_base.'\".');
|
||||||
|
@ -111,21 +114,21 @@ class LdapSync extends Command
|
||||||
|
|
||||||
/* Determine which location to assign users to by default. */
|
/* Determine which location to assign users to by default. */
|
||||||
$location = null; // TODO - this would be better called "$default_location", which is more explicit about its purpose
|
$location = null; // TODO - this would be better called "$default_location", which is more explicit about its purpose
|
||||||
|
|
||||||
if ($this->option('location') != '') {
|
if ($this->option('location') != '') {
|
||||||
if ($location = Location::where('name', '=', $this->option('location'))->first()) {
|
if ($location = Location::where('name', '=', $this->option('location'))->first()) {
|
||||||
Log::debug('Location name '.$this->option('location').' passed');
|
Log::debug('Location name ' . $this->option('location') . ' passed');
|
||||||
Log::debug('Importing to '.$location->name.' ('.$location->id.')');
|
Log::debug('Importing to ' . $location->name . ' (' . $location->id . ')');
|
||||||
}
|
}
|
||||||
|
|
||||||
} elseif ($this->option('location_id') != '') {
|
} elseif ($this->option('location_id') != '') {
|
||||||
if ($location = Location::where('id', '=', $this->option('location_id'))->first()) {
|
foreach($this->option('location_id') as $location_id) {
|
||||||
Log::debug('Location ID '.$this->option('location_id').' passed');
|
if ($location = Location::where('id', '=', $location_id)->first()) {
|
||||||
Log::debug('Importing to '.$location->name.' ('.$location->id.')');
|
Log::debug('Location ID ' . $location_id . ' passed');
|
||||||
|
Log::debug('Importing to ' . $location->name . ' (' . $location->id . ')');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (! isset($location)) {
|
if (! isset($location)) {
|
||||||
Log::debug('That location is invalid or a location was not provided, so no location will be assigned by default.');
|
Log::debug('That location is invalid or a location was not provided, so no location will be assigned by default.');
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,6 +150,11 @@ class Handler extends ExceptionHandler
|
||||||
return redirect()->guest('login');
|
return redirect()->guest('login');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function invalidJson($request, ValidationException $exception)
|
||||||
|
{
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('error', null, $exception->errors()), 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of the inputs that are never flashed for validation exceptions.
|
* A list of the inputs that are never flashed for validation exceptions.
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace App\Http\Controllers\Api;
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
use App\Events\CheckoutableCheckedIn;
|
use App\Events\CheckoutableCheckedIn;
|
||||||
|
use App\Http\Requests\StoreAssetRequest;
|
||||||
use Illuminate\Support\Facades\Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
@ -33,6 +34,7 @@ use TCPDF;
|
||||||
use Validator;
|
use Validator;
|
||||||
use Route;
|
use Route;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class controls all actions related to assets for
|
* This class controls all actions related to assets for
|
||||||
* the Snipe-IT Asset Management application.
|
* the Snipe-IT Asset Management application.
|
||||||
|
@ -532,10 +534,8 @@ class AssetsController extends Controller
|
||||||
* @since [v4.0]
|
* @since [v4.0]
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function store(ImageUploadRequest $request)
|
public function store(StoreAssetRequest $request)
|
||||||
{
|
{
|
||||||
$this->authorize('create', Asset::class);
|
|
||||||
|
|
||||||
$asset = new Asset();
|
$asset = new Asset();
|
||||||
$asset->model()->associate(AssetModel::find((int) $request->get('model_id')));
|
$asset->model()->associate(AssetModel::find((int) $request->get('model_id')));
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,10 @@ use App\Models\AssetModel;
|
||||||
use App\Models\Category;
|
use App\Models\Category;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
use App\Models\Labels\Label;
|
use App\Models\Labels\Label;
|
||||||
|
use App\Models\Location;
|
||||||
use App\Models\Manufacturer;
|
use App\Models\Manufacturer;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
|
use App\Models\Supplier;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\View\Label as LabelView;
|
use App\View\Label as LabelView;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
@ -33,18 +35,20 @@ class LabelsController extends Controller
|
||||||
$exampleAsset->name = 'JEN-867-5309';
|
$exampleAsset->name = 'JEN-867-5309';
|
||||||
$exampleAsset->asset_tag = '100001';
|
$exampleAsset->asset_tag = '100001';
|
||||||
$exampleAsset->serial = 'SN9876543210';
|
$exampleAsset->serial = 'SN9876543210';
|
||||||
|
$exampleAsset->asset_eol_date = '2025-01-01';
|
||||||
|
$exampleAsset->order_number = '12345';
|
||||||
|
$exampleAsset->purchase_date = '2023-01-01';
|
||||||
|
$exampleAsset->status_id = 1;
|
||||||
|
|
||||||
$exampleAsset->company = new Company();
|
$exampleAsset->company = new Company([
|
||||||
$exampleAsset->company->id = 999999;
|
'name' => 'Test Company Limited',
|
||||||
$exampleAsset->company->name = 'Test Company Limited';
|
'phone' => '1-555-555-5555',
|
||||||
$exampleAsset->company->image = 'company-image-test.png';
|
'email' => 'company@example.com',
|
||||||
|
]);
|
||||||
|
|
||||||
$exampleAsset->assignedto = new User();
|
$exampleAsset->setRelation('assignedTo', new User(['first_name' => 'Luke', 'last_name' => 'Skywalker']));
|
||||||
$exampleAsset->assignedto->id = 999999;
|
$exampleAsset->defaultLoc = new Location(['name' => 'Building 1', 'phone' => '1-555-555-5555']);
|
||||||
$exampleAsset->assignedto->first_name = 'Test';
|
$exampleAsset->location = new Location(['name' => 'Building 2', 'phone' => '1-555-555-5555']);
|
||||||
$exampleAsset->assignedto->last_name = 'Person';
|
|
||||||
$exampleAsset->assignedto->username = 'Test.Person';
|
|
||||||
$exampleAsset->assignedto->employee_num = '0123456789';
|
|
||||||
|
|
||||||
$exampleAsset->model = new AssetModel();
|
$exampleAsset->model = new AssetModel();
|
||||||
$exampleAsset->model->id = 999999;
|
$exampleAsset->model->id = 999999;
|
||||||
|
@ -53,6 +57,10 @@ class LabelsController extends Controller
|
||||||
$exampleAsset->model->manufacturer = new Manufacturer();
|
$exampleAsset->model->manufacturer = new Manufacturer();
|
||||||
$exampleAsset->model->manufacturer->id = 999999;
|
$exampleAsset->model->manufacturer->id = 999999;
|
||||||
$exampleAsset->model->manufacturer->name = 'Test Manufacturing Inc.';
|
$exampleAsset->model->manufacturer->name = 'Test Manufacturing Inc.';
|
||||||
|
$exampleAsset->model->manufacturer->support_email = 'support@test.com';
|
||||||
|
$exampleAsset->model->manufacturer->support_phone = '1-555-555-5555';
|
||||||
|
$exampleAsset->model->manufacturer->support_url = 'https://example.com';
|
||||||
|
$exampleAsset->supplier = new Supplier(['name' => 'Test Company Limited']);
|
||||||
$exampleAsset->model->category = new Category();
|
$exampleAsset->model->category = new Category();
|
||||||
$exampleAsset->model->category->id = 999999;
|
$exampleAsset->model->category->id = 999999;
|
||||||
$exampleAsset->model->category->name = 'Test Category';
|
$exampleAsset->model->category->name = 'Test Category';
|
||||||
|
|
|
@ -7,6 +7,7 @@ use App\Helpers\StorageHelper;
|
||||||
use App\Http\Requests\ImageUploadRequest;
|
use App\Http\Requests\ImageUploadRequest;
|
||||||
use App\Http\Requests\SettingsSamlRequest;
|
use App\Http\Requests\SettingsSamlRequest;
|
||||||
use App\Http\Requests\SetupUserRequest;
|
use App\Http\Requests\SetupUserRequest;
|
||||||
|
use App\Models\CustomField;
|
||||||
use App\Models\Group;
|
use App\Models\Group;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
|
@ -809,9 +810,10 @@ class SettingsController extends Controller
|
||||||
*/
|
*/
|
||||||
public function getLabels()
|
public function getLabels()
|
||||||
{
|
{
|
||||||
$setting = Setting::getSettings();
|
return view('settings.labels', [
|
||||||
|
'setting' => Setting::getSettings(),
|
||||||
return view('settings.labels', compact('setting'));
|
'customFields' => CustomField::all(),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -49,19 +49,19 @@ class LDAPImportController extends Controller
|
||||||
{
|
{
|
||||||
$this->authorize('update', User::class);
|
$this->authorize('update', User::class);
|
||||||
// Call Artisan LDAP import command.
|
// Call Artisan LDAP import command.
|
||||||
$location_id = $request->input('location_id');
|
|
||||||
Artisan::call('snipeit:ldap-sync', ['--location_id' => $location_id, '--json_summary' => true]);
|
Artisan::call('snipeit:ldap-sync', ['--location_id' => $request->input('location_id'), '--json_summary' => true]);
|
||||||
|
|
||||||
// Collect and parse JSON summary.
|
// Collect and parse JSON summary.
|
||||||
$ldap_results_json = Artisan::output();
|
$ldap_results_json = Artisan::output();
|
||||||
$ldap_results = json_decode($ldap_results_json, true);
|
$ldap_results = json_decode($ldap_results_json, true);
|
||||||
|
|
||||||
if (!$ldap_results) {
|
if (!$ldap_results) {
|
||||||
return redirect()->back()->withInput()->with('error', trans('general.no_results'));
|
return redirect()->back()->withInput()->with('error', trans('general.no_results'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Direct user to appropriate status page.
|
// Direct user to appropriate status page.
|
||||||
if ($ldap_results['error']) {
|
if ($ldap_results['error']) {
|
||||||
|
|
||||||
return redirect()->back()->withInput()->with('error', $ldap_results['error_message']);
|
return redirect()->back()->withInput()->with('error', $ldap_results['error_message']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
40
app/Http/Requests/StoreAssetRequest.php
Normal file
40
app/Http/Requests/StoreAssetRequest.php
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use App\Models\Asset;
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Support\Facades\Gate;
|
||||||
|
|
||||||
|
class StoreAssetRequest extends ImageUploadRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return Gate::allows('create', new Asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function prepareForValidation(): void
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
$rules = array_merge(
|
||||||
|
(new Asset)->getRules(),
|
||||||
|
parent::rules(),
|
||||||
|
);
|
||||||
|
|
||||||
|
return $rules;
|
||||||
|
}
|
||||||
|
}
|
|
@ -144,7 +144,7 @@ class AssetImporter extends ItemImporter
|
||||||
// If we have a target to checkout to, lets do so.
|
// If we have a target to checkout to, lets do so.
|
||||||
//-- user_id is a property of the abstract class Importer, which this class inherits from and it's setted by
|
//-- user_id is a property of the abstract class Importer, which this class inherits from and it's setted by
|
||||||
//-- the class that needs to use it (command importer or GUI importer inside the project).
|
//-- the class that needs to use it (command importer or GUI importer inside the project).
|
||||||
if (isset($target)) {
|
if (isset($target) && ($target !== false)) {
|
||||||
if (!is_null($asset->assigned_to)){
|
if (!is_null($asset->assigned_to)){
|
||||||
if ($asset->assigned_to != $target->id){
|
if ($asset->assigned_to != $target->id){
|
||||||
event(new CheckoutableCheckedIn($asset, User::find($asset->assigned_to), Auth::user(), $asset->notes, date('Y-m-d H:i:s')));
|
event(new CheckoutableCheckedIn($asset, User::find($asset->assigned_to), Auth::user(), $asset->notes, date('Y-m-d H:i:s')));
|
||||||
|
|
|
@ -91,7 +91,7 @@ class Asset extends Depreciable
|
||||||
|
|
||||||
protected $rules = [
|
protected $rules = [
|
||||||
'name' => 'max:255|nullable',
|
'name' => 'max:255|nullable',
|
||||||
'model_id' => 'required|integer|exists:models,id,deleted_at,NULL',
|
'model_id' => 'required|integer|exists:models,id,deleted_at,NULL|not_array',
|
||||||
'status_id' => 'required|integer|exists:status_labels,id',
|
'status_id' => 'required|integer|exists:status_labels,id',
|
||||||
'company_id' => 'integer|nullable',
|
'company_id' => 'integer|nullable',
|
||||||
'warranty_months' => 'numeric|nullable|digits_between:0,240',
|
'warranty_months' => 'numeric|nullable|digits_between:0,240',
|
||||||
|
@ -100,7 +100,7 @@ class Asset extends Depreciable
|
||||||
'expected_checkin' => 'date|nullable',
|
'expected_checkin' => 'date|nullable',
|
||||||
'location_id' => 'exists:locations,id|nullable',
|
'location_id' => 'exists:locations,id|nullable',
|
||||||
'rtd_location_id' => 'exists:locations,id|nullable',
|
'rtd_location_id' => 'exists:locations,id|nullable',
|
||||||
'asset_tag' => 'required|min:1|max:255|unique_undeleted',
|
'asset_tag' => 'required|min:1|max:255|unique_undeleted:assets,asset_tag',
|
||||||
'purchase_date' => 'date|date_format:Y-m-d|nullable',
|
'purchase_date' => 'date|date_format:Y-m-d|nullable',
|
||||||
'serial' => 'unique_serial|nullable',
|
'serial' => 'unique_serial|nullable',
|
||||||
'purchase_cost' => 'numeric|nullable|gte:0',
|
'purchase_cost' => 'numeric|nullable|gte:0',
|
||||||
|
|
|
@ -14,6 +14,14 @@ class FieldOption {
|
||||||
|
|
||||||
public function getValue(Asset $asset) {
|
public function getValue(Asset $asset) {
|
||||||
$dataPath = collect(explode('.', $this->dataSource));
|
$dataPath = collect(explode('.', $this->dataSource));
|
||||||
|
|
||||||
|
// assignedTo directly on the asset is a special case where
|
||||||
|
// we want to avoid returning the property directly
|
||||||
|
// and instead return the entity's presented name.
|
||||||
|
if ($dataPath[0] === 'assignedTo'){
|
||||||
|
return $asset->assignedTo ? $asset->assignedTo->present()->fullName() : null;
|
||||||
|
}
|
||||||
|
|
||||||
return $dataPath->reduce(function ($myValue, $path) {
|
return $dataPath->reduce(function ($myValue, $path) {
|
||||||
try { return $myValue ? $myValue->{$path} : ${$myValue}; }
|
try { return $myValue ? $myValue->{$path} : ${$myValue}; }
|
||||||
catch (\Exception $e) { return $myValue; }
|
catch (\Exception $e) { return $myValue; }
|
||||||
|
|
|
@ -48,6 +48,8 @@ class ValidationServiceProvider extends ServiceProvider
|
||||||
// Unique only if undeleted
|
// Unique only if undeleted
|
||||||
// This works around the use case where multiple deleted items have the same unique attribute.
|
// This works around the use case where multiple deleted items have the same unique attribute.
|
||||||
// (I think this is a bug in Laravel's validator?)
|
// (I think this is a bug in Laravel's validator?)
|
||||||
|
// $parameters is the rule parameters, like `unique_undeleted:users,id` - $parameters[0] is users, $parameters[1] is id
|
||||||
|
// the UniqueUndeletedTrait prefills these so you can just use `unique_undeleted` in your rules (but this would only work directly in the model)
|
||||||
Validator::extend('unique_undeleted', function ($attribute, $value, $parameters, $validator) {
|
Validator::extend('unique_undeleted', function ($attribute, $value, $parameters, $validator) {
|
||||||
if (count($parameters)) {
|
if (count($parameters)) {
|
||||||
$count = DB::table($parameters[0])->select('id')->where($attribute, '=', $value)->whereNull('deleted_at')->where('id', '!=', $parameters[1])->count();
|
$count = DB::table($parameters[0])->select('id')->where($attribute, '=', $value)->whereNull('deleted_at')->where('id', '!=', $parameters[1])->count();
|
||||||
|
|
|
@ -304,7 +304,54 @@
|
||||||
<label style="grid-area: label-title">Label</label>
|
<label style="grid-area: label-title">Label</label>
|
||||||
<input style="grid-area: label-field" x-model="option.label" />
|
<input style="grid-area: label-field" x-model="option.label" />
|
||||||
<label style="grid-area: source-title">DataSource</label>
|
<label style="grid-area: source-title">DataSource</label>
|
||||||
<input style="grid-area: source-field" x-model="option.datasource" />
|
<select style="grid-area: source-field" x-model="option.datasource">
|
||||||
|
<optgroup label="Asset">
|
||||||
|
<option value="asset_tag">Asset Tag</option>
|
||||||
|
<option value="name">Asset Name</option>
|
||||||
|
<option value="serial">Asset Serial</option>
|
||||||
|
<option value="asset_eol_date">Asset EOL Date</option>
|
||||||
|
<option value="order_number">Asset Order Number</option>
|
||||||
|
<option value="purchase_date">Asset Purchase Date</option>
|
||||||
|
<option value="assignedTo">Assigned To</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="Asset Model">
|
||||||
|
<option value="model.name">Asset Model Name</option>
|
||||||
|
<option value="model.model_number">Asset Model Number</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="Manufacturer">
|
||||||
|
<option value="model.manufacturer.name">Manufacturer Name</option>
|
||||||
|
<option value="model.manufacturer.support_email">Manufacturer Support Email</option>
|
||||||
|
<option value="model.manufacturer.support_phone">Manufacturer Support Phone</option>
|
||||||
|
<option value="model.manufacturer.support_url">Manufacturer Support URL</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="Category">
|
||||||
|
<option value="model.category.name">Category Name</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="Status">
|
||||||
|
<option value="assetstatus.name">Status</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="Supplier">
|
||||||
|
<option value="supplier.name">Supplier Name</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="Default Location">
|
||||||
|
<option value="defaultLoc.name">Default Location Name</option>
|
||||||
|
<option value="defaultLoc.phone">Default Location Phone</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="Location">
|
||||||
|
<option value="location.name">Location Name</option>
|
||||||
|
<option value="location.phone">Location Phone</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="Company">
|
||||||
|
<option value="company.email">Company Email</option>
|
||||||
|
<option value="company.name">Company Name</option>
|
||||||
|
<option value="company.phone">Company Phone</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="Custom Fields">
|
||||||
|
@foreach($customFields as $customField)
|
||||||
|
<option value="{{ $customField->db_column }}">{{ $customField->name }}</option>
|
||||||
|
@endforeach
|
||||||
|
</optgroup>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -216,7 +216,7 @@
|
||||||
{{ Form::label('label2_fields', trans('admin/settings/general.label2_fields')) }}
|
{{ Form::label('label2_fields', trans('admin/settings/general.label2_fields')) }}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-9">
|
<div class="col-md-9">
|
||||||
@include('partials.label2-field-definitions', [ 'name' => 'label2_fields', 'value' => old('label2_fields', $setting->label2_fields) ])
|
@include('partials.label2-field-definitions', [ 'name' => 'label2_fields', 'value' => old('label2_fields', $setting->label2_fields), 'customFields' => $customFields ])
|
||||||
{!! $errors->first('label2_fields', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
{!! $errors->first('label2_fields', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||||
<p class="help-block">{{ trans('admin/settings/general.label2_fields_help') }}</p>
|
<p class="help-block">{{ trans('admin/settings/general.label2_fields_help') }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<!-- Location -->
|
<!-- Location -->
|
||||||
@include ('partials.forms.edit.location-select', ['translated_name' => trans('general.location'), 'fieldname' => 'location_id'])
|
@include ('partials.forms.edit.location-select', ['translated_name' => trans('general.location'), 'fieldname' => 'location_id[]', 'multiple' => true])
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
19
tests/Feature/Api/Assets/AssetStoreTest.php
Normal file
19
tests/Feature/Api/Assets/AssetStoreTest.php
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature\Api\Assets;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use Tests\Support\InteractsWithSettings;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class AssetStoreTest extends TestCase
|
||||||
|
{
|
||||||
|
use InteractsWithSettings;
|
||||||
|
|
||||||
|
public function testRequiresPermissionToCreateAsset()
|
||||||
|
{
|
||||||
|
$this->actingAsForApi(User::factory()->create())
|
||||||
|
->postJson(route('api.assets.store'))
|
||||||
|
->assertForbidden();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue