Merge pull request #17174 from grokability/fixes-17163-permissions-on-maintenances

Fixed #17163 - insufficient permissions on editing an asset maintenance
This commit is contained in:
snipe
2025-06-14 16:43:27 +01:00
committed by GitHub
7 changed files with 122 additions and 99 deletions

View File

@@ -19,19 +19,6 @@ use \Illuminate\Http\RedirectResponse;
*/
class AssetMaintenancesController extends Controller
{
/**
* Checks for permissions for this action.
*
* @todo This should be replaced with middleware and/or policies
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
* @since [v1.8]
*/
private static function getInsufficientPermissionsRedirect(): RedirectResponse
{
return redirect()->route('maintenances.index')
->with('error', trans('general.insufficient_permissions'));
}
/**
* Returns a view that invokes the ajax tables which actually contains
@@ -88,10 +75,8 @@ class AssetMaintenancesController extends Controller
$assets = Asset::whereIn('id', $request->input('selected_assets'))->get();
// Loop through the selected assets
foreach ($assets as $asset) {
if ((! Company::isCurrentUserHasAccess($asset)) && ($asset != null)) {
return static::getInsufficientPermissionsRedirect();
}
$assetMaintenance = new AssetMaintenance();
$assetMaintenance->supplier_id = $request->input('supplier_id');
@@ -133,26 +118,19 @@ class AssetMaintenancesController extends Controller
*
* @see AssetMaintenancesController::postEdit() method that stores the data
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @param int $assetMaintenanceId
* @version v1.0
* @since [v1.8]
*/
public function edit(AssetMaintenance $maintenance) : View | RedirectResponse
{
$this->authorize('update', Asset::class);
if ((!$maintenance->asset) || ($maintenance->asset->deleted_at!='')) {
return redirect()->route('maintenances.index')->with('error', 'asset does not exist');
} elseif (! Company::isCurrentUserHasAccess($maintenance->asset)) {
return static::getInsufficientPermissionsRedirect();
}
// Prepare Improvement Type List
$assetMaintenanceType = ['' => trans('general.select')] + AssetMaintenance::getImprovementOptions();
$this->authorize('update', $maintenance->asset);
return view('asset_maintenances/edit')
->with('selectedAsset', null)
->with('assetMaintenanceType', $assetMaintenanceType)
->with('item', $maintenance);
->with('selected_assets', $maintenance->asset->pluck('id')->toArray())
->with('asset_ids', request()->input('asset_ids', []))
->with('assetMaintenanceType', AssetMaintenance::getImprovementOptions())
->with('item', $maintenance);
}
/**
@@ -168,33 +146,21 @@ class AssetMaintenancesController extends Controller
public function update(Request $request, AssetMaintenance $maintenance) : View | RedirectResponse
{
$this->authorize('update', Asset::class);
if ((!$maintenance->asset) || ($maintenance->asset->deleted_at!='')) {
return redirect()->route('maintenances.index')->with('error', 'asset does not exist');
} elseif (! Company::isCurrentUserHasAccess($maintenance->asset)) {
return static::getInsufficientPermissionsRedirect();
}
$this->authorize('update', $maintenance->asset);
$maintenance->supplier_id = $request->input('supplier_id');
$maintenance->is_warranty = $request->input('is_warranty');
$maintenance->is_warranty = $request->input('is_warranty', 0);
$maintenance->cost = $request->input('cost');
$maintenance->notes = $request->input('notes');
$asset = Asset::find(request('asset_id'));
if (! Company::isCurrentUserHasAccess($asset)) {
return static::getInsufficientPermissionsRedirect();
}
// Save the asset maintenance data
$maintenance->asset_id = $request->input('asset_id');
$maintenance->asset_maintenance_type = $request->input('asset_maintenance_type');
$maintenance->title = $request->input('title');
$maintenance->start_date = $request->input('start_date');
$maintenance->completion_date = $request->input('completion_date');
if (($maintenance->completion_date == null)
) {
// Todo - put this in a getter/setter?
if (($maintenance->completion_date == null))
{
if (($maintenance->asset_maintenance_time !== 0)
|| (! is_null($maintenance->asset_maintenance_time))
) {
@@ -211,10 +177,7 @@ class AssetMaintenancesController extends Controller
$maintenance->asset_maintenance_time = (int) $completionDate->diffInDays($startDate, true);
}
// Was the asset maintenance created?
if ($maintenance->save()) {
// Redirect to the new asset maintenance page
return redirect()->route('maintenances.index')
->with('success', trans('admin/asset_maintenances/message.edit.success'));
}
@@ -230,21 +193,12 @@ class AssetMaintenancesController extends Controller
* @version v1.0
* @since [v1.8]
*/
public function destroy($assetMaintenanceId) : RedirectResponse
public function destroy(AssetMaintenance $maintenance) : RedirectResponse
{
$this->authorize('update', Asset::class);
// Check if the asset maintenance exists
if (is_null($assetMaintenance = AssetMaintenance::find($assetMaintenanceId))) {
// Redirect to the asset maintenance management page
return redirect()->route('maintenances.index')
->with('error', trans('admin/asset_maintenances/message.not_found'));
} elseif (! Company::isCurrentUserHasAccess($assetMaintenance->asset)) {
return static::getInsufficientPermissionsRedirect();
}
$this->authorize('update', $maintenance->asset);
// Delete the asset maintenance
$assetMaintenance->delete();
$maintenance->delete();
// Redirect to the asset_maintenance management page
return redirect()->route('maintenances.index')
->with('success', trans('admin/asset_maintenances/message.delete.success'));
@@ -260,11 +214,6 @@ class AssetMaintenancesController extends Controller
*/
public function show(AssetMaintenance $maintenance) : View | RedirectResponse
{
$this->authorize('view', Asset::class);
if (! Company::isCurrentUserHasAccess($maintenance->asset)) {
return static::getInsufficientPermissionsRedirect();
}
return view('asset_maintenances/view')->with('assetMaintenance', $maintenance);
}
}

View File

@@ -31,7 +31,7 @@ class AssetMaintenance extends Model implements ICompanyableChild
'title' => 'required|max:100',
'is_warranty' => 'boolean',
'start_date' => 'required|date_format:Y-m-d',
'completion_date' => 'date_format:Y-m-d|nullable',
'completion_date' => 'date_format:Y-m-d|nullable|after_or_equal:start_date',
'notes' => 'string|nullable',
'cost' => 'numeric|nullable',
];
@@ -166,6 +166,7 @@ class AssetMaintenance extends Model implements ICompanyableChild
return $this->belongsTo(\App\Models\Asset::class, 'asset_id')
->withTrashed();
}
/**
* Get the admin who created the maintenance

View File

@@ -414,13 +414,13 @@ class BreadcrumbsServiceProvider extends ServiceProvider
);
Breadcrumbs::for('maintenances.show', fn (Trail $trail, AssetMaintenance $maintenance) =>
$trail->parent('maintenances.index', route('locations.index'))
$trail->parent('maintenances.index', route('maintenances.index'))
->push($maintenance->title, route('maintenances.show', $maintenance))
);
Breadcrumbs::for('manufacturers.edit', fn (Trail $trail, Manufacturer $manufacturer) =>
$trail->parent('manufacturers.index', route('manufacturers.index'))
->push(trans('general.breadcrumb_button_actions.edit_item', ['name' => $manufacturer->name]), route('manufacturers.edit', $manufacturer))
Breadcrumbs::for('maintenances.edit', fn (Trail $trail, AssetMaintenance $maintenance) =>
$trail->parent('maintenances.index', route('maintenances.index'))
->push(trans('general.breadcrumb_button_actions.edit_item', ['name' => $maintenance->title]), route('maintenances.edit', $maintenance))
);

View File

@@ -32,13 +32,14 @@
{{ csrf_field() }}
<div class="box box-default">
<div class="box-header with-border">
<h2 class="box-title">
@if ($item)
{{ $item->name }}
@endif
</h2>
</div><!-- /.box-header -->
@if ($item->id)
<div class="box-header with-border">
<h2 class="box-title">
{{ $item->title }}
</h2>
</div><!-- /.box-header -->
@endif
<div class="box-body">
@@ -53,17 +54,63 @@
</div>
</div>
<!-- This is a new maintenance -->
@if (!$item->id)
@include ('partials.forms.edit.asset-select', [
'translated_name' => trans('general.assets'),
'fieldname' => 'selected_assets[]',
'multiple' => true,
'required' => true,
'select_id' => 'assigned_assets_select',
'asset_selector_div_id' => 'assets_to_checkout_div',
'asset_ids' => old('selected_assets')
])
@include ('partials.forms.edit.asset-select', [
'translated_name' => trans('general.assets'),
'fieldname' => 'selected_assets[]',
'multiple' => true,
'required' => true,
'select_id' => 'assigned_assets_select',
'asset_selector_div_id' => 'assets_for_maintenance_div',
'asset_ids' => $item->id ? $item->asset()->pluck('id')->toArray() : old('selected_assets'),
'asset_id' => $item->id ? $item->asset()->pluck('id')->toArray() : null
])
@else
@if ($item->asset->company)
<div class="form-group">
<label for="company" class="control-label col-md-3">
{{ trans('general.company') }}
</label>
<div class="col-md-9">
<p class="form-control-static">
{{ $item->asset->company->name }}
</p>
</div>
</div>
@endif
<div class="form-group">
<label for="asset" class="control-label col-md-3">
{{ trans('general.asset') }}
</label>
<div class="col-md-9">
<p class="form-control-static">
{{ $item->asset ? $item->asset->present()->fullName : '' }}
</p>
</div>
</div>
@if ($item->asset->location)
<div class="form-group">
<label for="location" class="control-label col-md-3">
{{ trans('general.location') }}
</label>
<div class="col-md-9">
<p class="form-control-static">
{{ $item->asset->location->name }}
</p>
</div>
</div>
@endif
@endif
@include ('partials.forms.edit.maintenance_type')
@@ -72,9 +119,11 @@
<!-- Start Date -->
<div class="form-group {{ $errors->has('start_date') ? ' has-error' : '' }}">
<label for="start_date" class="col-md-3 control-label">{{ trans('admin/asset_maintenances/form.start_date') }}</label>
<label for="start_date" class="col-md-3 control-label">
{{ trans('admin/asset_maintenances/form.start_date') }}
</label>
<div class="input-group col-md-3">
<div class="col-md-4">
<x-input.datepicker
name="start_date"
:value="old('start_date', $item->start_date)"
@@ -91,10 +140,10 @@
<div class="form-group {{ $errors->has('completion_date') ? ' has-error' : '' }}">
<label for="start_date" class="col-md-3 control-label">{{ trans('admin/asset_maintenances/form.completion_date') }}</label>
<div class="input-group col-md-3">
<div class="input-group col-md-4">
<x-input.datepicker
name="completion_date"
:value="old('start_date', $item->start_date)"
:value="old('start_date', $item->completion_date)"
placeholder="{{ trans('general.select_date') }}"
required="Helper::checkIfRequired($item, 'completion_date')"
/>

View File

@@ -49,6 +49,31 @@ use Carbon\Carbon;
</div>
</div> <!-- /row -->
@if ($assetMaintenance->asset->model)
<div class="row">
<div class="col-md-3">
{{ trans('general.asset_model') }}
</div>
<div class="col-md-9">
<a href="{{ route('models.show', $assetMaintenance->asset->model_id) }}">
{{ $assetMaintenance->asset->model->name }}
</a>
</div>
</div> <!-- /row -->
@endif
@if ($assetMaintenance->asset->company)
<div class="row">
<div class="col-md-3">
{{ trans('general.company') }}
</div>
<div class="col-md-9">
<a href="{{ route('companies.show', $assetMaintenance->asset->company_id) }}">
{{ $assetMaintenance->asset->company->name }}
</a>
</div>
</div> <!-- /row -->
@endif
@if ($assetMaintenance->supplier)

View File

@@ -10,7 +10,7 @@
name="{{ $fieldname }}"
style="width: 100%"
id="{{ (isset($select_id)) ? $select_id : 'assigned_asset_select' }}"
{{ (isset($multiple)) ? ' multiple' : '' }}
{{ ((isset($multiple)) && ($multiple === true)) ? ' multiple' : '' }}
{!! (!empty($asset_status_type)) ? ' data-asset-status-type="' . $asset_status_type . '"' : '' !!}
{!! (!empty($company_id)) ? ' data-company-id="' .$company_id.'"' : '' !!}
{{ ((isset($required) && ($required =='true'))) ? ' required' : '' }}

View File

@@ -20,27 +20,26 @@ class EditAssetMaintenanceTest extends TestCase
public function testCanUpdateAssetMaintenance()
{
$actor = User::factory()->superuser()->create();
$assetMaintenance = AssetMaintenance::factory()->create();
$asset = Asset::factory()->create();
$assetMaintenance = AssetMaintenance::factory()->create(['asset_id' => $asset]);
$supplier = Supplier::factory()->create();
$this->actingAs($actor)
->followingRedirects()
->put(route('maintenances.update', $assetMaintenance->id), [
->put(route('maintenances.update', $assetMaintenance), [
'title' => 'Test Maintenance',
'asset_id' => $asset->id,
'supplier_id' => $supplier->id,
'asset_maintenance_type' => 'Maintenance',
'start_date' => '2021-01-01',
'completion_date' => '2021-01-10',
'is_warranty' => '1',
'cost' => '100.00',
'is_warranty' => 1,
'cost' => '100.99',
'notes' => 'A note',
])
->assertOk();
$this->assertDatabaseHas('asset_maintenances', [
'asset_id' => $asset->id,
'supplier_id' => $supplier->id,
@@ -51,7 +50,7 @@ class EditAssetMaintenanceTest extends TestCase
'completion_date' => '2021-01-10',
'asset_maintenance_time' => '9',
'notes' => 'A note',
'cost' => '100.00',
'cost' => '100.99',
]);
}