Merge branch 'develop' into snipeit_v7_laravel10

This commit is contained in:
Brady Wetherington 2023-09-12 12:04:42 +01:00
commit c77f5eee8c
27 changed files with 333 additions and 130 deletions

View file

@ -2,6 +2,8 @@
namespace App\Helpers; namespace App\Helpers;
use App\Models\Accessory; use App\Models\Accessory;
use App\Models\Asset;
use App\Models\AssetModel;
use App\Models\Component; use App\Models\Component;
use App\Models\Consumable; use App\Models\Consumable;
use App\Models\CustomField; use App\Models\CustomField;
@ -643,6 +645,7 @@ class Helper
$consumables = Consumable::withCount('consumableAssignments as consumable_assignments_count')->whereNotNull('min_amt')->get(); $consumables = Consumable::withCount('consumableAssignments as consumable_assignments_count')->whereNotNull('min_amt')->get();
$accessories = Accessory::withCount('users as users_count')->whereNotNull('min_amt')->get(); $accessories = Accessory::withCount('users as users_count')->whereNotNull('min_amt')->get();
$components = Component::whereNotNull('min_amt')->get(); $components = Component::whereNotNull('min_amt')->get();
$asset_models = AssetModel::where('min_amt', '>', 0)->get();
$avail_consumables = 0; $avail_consumables = 0;
$items_array = []; $items_array = [];
@ -705,6 +708,28 @@ class Helper
} }
} }
foreach ($asset_models as $asset_model){
$asset = new Asset();
$total_owned = $asset->where('model_id', '=', $asset_model->id)->count();
$avail = $asset->where('model_id', '=', $asset_model->id)->whereNull('assigned_to')->count();
if ($avail < ($asset_model->min_amt)+ \App\Models\Setting::getSettings()->alert_threshold) {
if ($avail > 0) {
$percent = number_format((($avail / $total_owned) * 100), 0);
} else {
$percent = 100;
}
$items_array[$all_count]['id'] = $asset_model->id;
$items_array[$all_count]['name'] = $asset_model->name;
$items_array[$all_count]['type'] = 'models';
$items_array[$all_count]['percent'] = $percent;
$items_array[$all_count]['remaining'] = $avail;
$items_array[$all_count]['min_amt'] = $asset_model->min_amt;
$all_count++;
}
}
return $items_array; return $items_array;
} }

View file

@ -161,22 +161,19 @@ class AccessoriesFilesController extends Controller
->header('Content-Type', 'text/plain'); ->header('Content-Type', 'text/plain');
} else { } else {
// Display the file inline
if (request('inline') == 'true') {
$headers = [
'Content-Disposition' => 'inline',
];
return Storage::download($file, $log->filename, $headers);
}
// We have to override the URL stuff here, since local defaults in Laravel's Flysystem // We have to override the URL stuff here, since local defaults in Laravel's Flysystem
// won't work, as they're not accessible via the web // won't work, as they're not accessible via the web
if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer? if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer?
return StorageHelper::downloader($file); return StorageHelper::downloader($file);
} else {
if ($download != 'true') {
\Log::debug('display the file');
if ($contents = file_get_contents(Storage::url($file))) { // TODO - this will fail on private S3 files or large public ones
return Response::make(Storage::url($file)->header('Content-Type', mime_content_type($file)));
}
return JsonResponse::create(['error' => 'Failed validation: '], 500);
}
return StorageHelper::downloader($file);
} }
} }
} }

View file

@ -38,6 +38,7 @@ class AssetModelsController extends Controller
'image', 'image',
'name', 'name',
'model_number', 'model_number',
'min_amt',
'eol', 'eol',
'notes', 'notes',
'created_at', 'created_at',
@ -52,6 +53,7 @@ class AssetModelsController extends Controller
'models.image', 'models.image',
'models.name', 'models.name',
'model_number', 'model_number',
'min_amt',
'eol', 'eol',
'requestable', 'requestable',
'models.notes', 'models.notes',

View file

@ -76,6 +76,7 @@ class AssetModelsController extends Controller
$model->depreciation_id = $request->input('depreciation_id'); $model->depreciation_id = $request->input('depreciation_id');
$model->name = $request->input('name'); $model->name = $request->input('name');
$model->model_number = $request->input('model_number'); $model->model_number = $request->input('model_number');
$model->min_amt = $request->input('min_amt');
$model->manufacturer_id = $request->input('manufacturer_id'); $model->manufacturer_id = $request->input('manufacturer_id');
$model->category_id = $request->input('category_id'); $model->category_id = $request->input('category_id');
$model->notes = $request->input('notes'); $model->notes = $request->input('notes');
@ -153,6 +154,7 @@ class AssetModelsController extends Controller
$model->eol = $request->input('eol'); $model->eol = $request->input('eol');
$model->name = $request->input('name'); $model->name = $request->input('name');
$model->model_number = $request->input('model_number'); $model->model_number = $request->input('model_number');
$model->min_amt = $request->input('min_amt');
$model->manufacturer_id = $request->input('manufacturer_id'); $model->manufacturer_id = $request->input('manufacturer_id');
$model->category_id = $request->input('category_id'); $model->category_id = $request->input('category_id');
$model->notes = $request->input('notes'); $model->notes = $request->input('notes');

View file

@ -78,7 +78,7 @@ class AssetModelsFilesController extends Controller
* @return View * @return View
* @throws \Illuminate\Auth\Access\AuthorizationException * @throws \Illuminate\Auth\Access\AuthorizationException
*/ */
public function show($modelId = null, $fileId = null, $download = true) public function show($modelId = null, $fileId = null)
{ {
$model = AssetModel::find($modelId); $model = AssetModel::find($modelId);
// the asset is valid // the asset is valid
@ -99,12 +99,13 @@ class AssetModelsFilesController extends Controller
->header('Content-Type', 'text/plain'); ->header('Content-Type', 'text/plain');
} }
if ($download != 'true') { if (request('inline') == 'true') {
if ($contents = file_get_contents(Storage::url($file))) {
return Response::make(Storage::url($file)->header('Content-Type', mime_content_type($file)));
}
return JsonResponse::create(['error' => 'Failed validation: '], 500); $headers = [
'Content-Disposition' => 'inline',
];
return Storage::download($file, $log->filename, $headers);
} }
return StorageHelper::downloader($file); return StorageHelper::downloader($file);

View file

@ -79,7 +79,7 @@ class AssetFilesController extends Controller
* @return View * @return View
* @throws \Illuminate\Auth\Access\AuthorizationException * @throws \Illuminate\Auth\Access\AuthorizationException
*/ */
public function show($assetId = null, $fileId = null, $download = true) public function show($assetId = null, $fileId = null)
{ {
$asset = Asset::find($assetId); $asset = Asset::find($assetId);
// the asset is valid // the asset is valid
@ -103,12 +103,13 @@ class AssetFilesController extends Controller
->header('Content-Type', 'text/plain'); ->header('Content-Type', 'text/plain');
} }
if ($download != 'true') { if (request('inline') == 'true') {
if ($contents = file_get_contents(Storage::url($file))) {
return Response::make(Storage::url($file)->header('Content-Type', mime_content_type($file)));
}
return JsonResponse::create(['error' => 'Failed validation: '], 500); $headers = [
'Content-Disposition' => 'inline',
];
return Storage::download($file, $log->filename, $headers);
} }
return StorageHelper::downloader($file); return StorageHelper::downloader($file);

View file

@ -132,7 +132,7 @@ class ComponentsFilesController extends Controller
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
* @throws \Illuminate\Auth\Access\AuthorizationException * @throws \Illuminate\Auth\Access\AuthorizationException
*/ */
public function show($componentId = null, $fileId = null, $download = true) public function show($componentId = null, $fileId = null)
{ {
\Log::debug('Private filesystem is: '.config('filesystems.default')); \Log::debug('Private filesystem is: '.config('filesystems.default'));
$component = Component::find($componentId); $component = Component::find($componentId);
@ -157,20 +157,16 @@ class ComponentsFilesController extends Controller
->header('Content-Type', 'text/plain'); ->header('Content-Type', 'text/plain');
} else { } else {
// Display the file inline
if (request('inline') == 'true') {
$headers = [
'Content-Disposition' => 'inline',
];
return Storage::download($file, $log->filename, $headers);
}
if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer? if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer?
return StorageHelper::downloader($file); return StorageHelper::downloader($file);
} else {
if ($download != 'true') {
\Log::debug('display the file');
if ($contents = file_get_contents(Storage::url($file))) { // TODO - this will fail on private S3 files or large public ones
return Response::make(Storage::url($file)->header('Content-Type', mime_content_type($file)));
}
return JsonResponse::create(['error' => 'Failed validation: '], 500);
}
return StorageHelper::downloader($file);
} }
} }
} }

View file

@ -131,7 +131,7 @@ class ConsumablesFilesController extends Controller
* @return \Symfony\Consumable\HttpFoundation\Response * @return \Symfony\Consumable\HttpFoundation\Response
* @throws \Illuminate\Auth\Access\AuthorizationException * @throws \Illuminate\Auth\Access\AuthorizationException
*/ */
public function show($consumableId = null, $fileId = null, $download = true) public function show($consumableId = null, $fileId = null)
{ {
$consumable = Consumable::find($consumableId); $consumable = Consumable::find($consumableId);
@ -155,22 +155,19 @@ class ConsumablesFilesController extends Controller
->header('Content-Type', 'text/plain'); ->header('Content-Type', 'text/plain');
} else { } else {
// Display the file inline
if (request('inline') == 'true') {
$headers = [
'Content-Disposition' => 'inline',
];
return Storage::download($file, $log->filename, $headers);
}
// We have to override the URL stuff here, since local defaults in Laravel's Flysystem // We have to override the URL stuff here, since local defaults in Laravel's Flysystem
// won't work, as they're not accessible via the web // won't work, as they're not accessible via the web
if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer? if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer?
return StorageHelper::downloader($file); return StorageHelper::downloader($file);
} else {
if ($download != 'true') {
\Log::debug('display the file');
if ($contents = file_get_contents(Storage::url($file))) { // TODO - this will fail on private S3 files or large public ones
return Response::make(Storage::url($file)->header('Content-Type', mime_content_type($file)));
}
return JsonResponse::create(['error' => 'Failed validation: '], 500);
}
return StorageHelper::downloader($file);
} }
} }
} }

View file

@ -152,21 +152,19 @@ class LicenseFilesController extends Controller
->header('Content-Type', 'text/plain'); ->header('Content-Type', 'text/plain');
} else { } else {
if (request('inline') == 'true') {
$headers = [
'Content-Disposition' => 'inline',
];
return Storage::download($file, $log->filename, $headers);
}
// We have to override the URL stuff here, since local defaults in Laravel's Flysystem // We have to override the URL stuff here, since local defaults in Laravel's Flysystem
// won't work, as they're not accessible via the web // won't work, as they're not accessible via the web
if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer? if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer?
return StorageHelper::downloader($file); return StorageHelper::downloader($file);
} else {
if ($download != 'true') {
\Log::debug('display the file');
if ($contents = file_get_contents(Storage::url($file))) { // TODO - this will fail on private S3 files or large public ones
return Response::make(Storage::url($file)->header('Content-Type', mime_content_type($file)));
}
return JsonResponse::create(['error' => 'Failed validation: '], 500);
}
return StorageHelper::downloader($file);
} }
} }

View file

@ -1021,7 +1021,12 @@ class ReportsController extends Controller
$assetsForReport = $acceptances $assetsForReport = $acceptances
->filter(function ($acceptance) { ->filter(function ($acceptance) {
return $acceptance->checkoutable_type == 'App\Models\Asset'; $acceptance_checkoutable_flag = false;
if ($acceptance->checkoutable){
$acceptance_checkoutable_flag = $acceptance->checkoutable->checkedOutToUser();
}
return $acceptance->checkoutable_type == 'App\Models\Asset' && $acceptance_checkoutable_flag;
}) })
->map(function($acceptance) { ->map(function($acceptance) {
return ['assetItem' => $acceptance->checkoutable, 'acceptance' => $acceptance]; return ['assetItem' => $acceptance->checkoutable, 'acceptance' => $acceptance];

View file

@ -2,6 +2,7 @@
namespace App\Http\Controllers\Users; namespace App\Http\Controllers\Users;
use App\Helpers\StorageHelper;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Http\Requests\AssetFileRequest; use App\Http\Requests\AssetFileRequest;
use App\Models\Actionlog; use App\Models\Actionlog;
@ -139,18 +140,25 @@ class UserFilesController extends Controller
// the license is valid // the license is valid
if (isset($user->id)) { if (isset($user->id)) {
$this->authorize('view', $user); $this->authorize('view', $user);
$log = Actionlog::find($fileId); $log = Actionlog::find($fileId);
$file = $log->get_src('users');
return Response::download($file); //FIXME this doesn't use the new StorageHelper yet, but it's complicated... // Display the file inline
if (request('inline') == 'true') {
$headers = [
'Content-Disposition' => 'inline',
];
return Storage::download('private_uploads/users/'.$log->filename, $log->filename, $headers);
} }
// Prepare the error message
$error = trans('admin/users/message.user_not_found', ['id' => $userId]);
// Redirect to the licence management page return Storage::download('private_uploads/users/'.$log->filename);
return redirect()->route('users.index')->with('error', $error);
}
// Redirect to the user management page if the user doesn't exist
return redirect()->route('users.index')->with('error', trans('admin/users/message.user_not_found', ['id' => $userId]));
} }
} }

View file

@ -32,6 +32,7 @@ class SaveUserRequest extends FormRequest
public function rules() public function rules()
{ {
$rules = [ $rules = [
'department_id' => 'nullable|exists:departments,id',
'manager_id' => 'nullable|exists:users,id', 'manager_id' => 'nullable|exists:users,id',
]; ];

View file

@ -68,8 +68,8 @@ class ActionlogsTransformer
} }
} }
$clean_meta = $this->changedInfo($clean_meta);
} }
$clean_meta= $this->changedInfo($clean_meta);
} }
$file_url = ''; $file_url = '';

View file

@ -47,6 +47,7 @@ class AssetModelsTransformer
] : null, ] : null,
'image' => ($assetmodel->image != '') ? Storage::disk('public')->url('models/'.e($assetmodel->image)) : null, 'image' => ($assetmodel->image != '') ? Storage::disk('public')->url('models/'.e($assetmodel->image)) : null,
'model_number' => e($assetmodel->model_number), 'model_number' => e($assetmodel->model_number),
'min_amt' => ($assetmodel->min_amt) ? (int) $assetmodel->min_amt : null,
'depreciation' => ($assetmodel->depreciation) ? [ 'depreciation' => ($assetmodel->depreciation) ? [
'id' => (int) $assetmodel->depreciation->id, 'id' => (int) $assetmodel->depreciation->id,
'name'=> e($assetmodel->depreciation->name), 'name'=> e($assetmodel->depreciation->name),

View file

@ -29,6 +29,7 @@ class AssetModel extends SnipeModel
protected $rules = [ protected $rules = [
'name' => 'required|min:1|max:255', 'name' => 'required|min:1|max:255',
'model_number' => 'max:255|nullable', 'model_number' => 'max:255|nullable',
'min_amt' => 'integer|min:0|nullable',
'category_id' => 'required|integer|exists:categories,id', 'category_id' => 'required|integer|exists:categories,id',
'manufacturer_id' => 'integer|exists:manufacturers,id|nullable', 'manufacturer_id' => 'integer|exists:manufacturers,id|nullable',
'eol' => 'integer:min:0|max:240|nullable', 'eol' => 'integer:min:0|max:240|nullable',
@ -65,6 +66,7 @@ class AssetModel extends SnipeModel
'fieldset_id', 'fieldset_id',
'image', 'image',
'manufacturer_id', 'manufacturer_id',
'min_amt',
'model_number', 'model_number',
'name', 'name',
'notes', 'notes',

View file

@ -65,6 +65,14 @@ class AssetModelPresenter extends Presenter
'title' => trans('admin/models/table.modelnumber'), 'title' => trans('admin/models/table.modelnumber'),
'visible' => true, 'visible' => true,
], ],
[
'field' => 'min_amt',
'searchable' => false,
'sortable' => true,
'switchable' => true,
'title' => trans('mail.min_QTY'),
'visible' => true,
],
[ [
'field' => 'assets_count', 'field' => 'assets_count',
'searchable' => false, 'searchable' => false,

102
composer.lock generated
View file

@ -191,16 +191,16 @@
}, },
{ {
"name": "aws/aws-sdk-php", "name": "aws/aws-sdk-php",
"version": "3.281.2", "version": "3.281.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/aws/aws-sdk-php.git", "url": "https://github.com/aws/aws-sdk-php.git",
"reference": "5b33690b4ebc32a75164be0d6805d393a3ca9df9" "reference": "c37035bcfb67a9d54f91dae303b3fe8f98ea59f4"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/5b33690b4ebc32a75164be0d6805d393a3ca9df9", "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/c37035bcfb67a9d54f91dae303b3fe8f98ea59f4",
"reference": "5b33690b4ebc32a75164be0d6805d393a3ca9df9", "reference": "c37035bcfb67a9d54f91dae303b3fe8f98ea59f4",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -280,9 +280,9 @@
"support": { "support": {
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
"issues": "https://github.com/aws/aws-sdk-php/issues", "issues": "https://github.com/aws/aws-sdk-php/issues",
"source": "https://github.com/aws/aws-sdk-php/tree/3.281.2" "source": "https://github.com/aws/aws-sdk-php/tree/3.281.4"
}, },
"time": "2023-09-07T18:06:59+00:00" "time": "2023-09-11T18:07:49+00:00"
}, },
{ {
"name": "bacon/bacon-qr-code", "name": "bacon/bacon-qr-code",
@ -3725,16 +3725,16 @@
}, },
{ {
"name": "league/flysystem", "name": "league/flysystem",
"version": "3.15.1", "version": "3.16.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/thephpleague/flysystem.git", "url": "https://github.com/thephpleague/flysystem.git",
"reference": "a141d430414fcb8bf797a18716b09f759a385bed" "reference": "4fdf372ca6b63c6e281b1c01a624349ccb757729"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/a141d430414fcb8bf797a18716b09f759a385bed", "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/4fdf372ca6b63c6e281b1c01a624349ccb757729",
"reference": "a141d430414fcb8bf797a18716b09f759a385bed", "reference": "4fdf372ca6b63c6e281b1c01a624349ccb757729",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3743,6 +3743,8 @@
"php": "^8.0.2" "php": "^8.0.2"
}, },
"conflict": { "conflict": {
"async-aws/core": "<1.19.0",
"async-aws/s3": "<1.14.0",
"aws/aws-sdk-php": "3.209.31 || 3.210.0", "aws/aws-sdk-php": "3.209.31 || 3.210.0",
"guzzlehttp/guzzle": "<7.0", "guzzlehttp/guzzle": "<7.0",
"guzzlehttp/ringphp": "<1.1.1", "guzzlehttp/ringphp": "<1.1.1",
@ -3762,7 +3764,7 @@
"microsoft/azure-storage-blob": "^1.1", "microsoft/azure-storage-blob": "^1.1",
"phpseclib/phpseclib": "^3.0.14", "phpseclib/phpseclib": "^3.0.14",
"phpstan/phpstan": "^0.12.26", "phpstan/phpstan": "^0.12.26",
"phpunit/phpunit": "^9.5.11", "phpunit/phpunit": "^9.5.11|^10.0",
"sabre/dav": "^4.3.1" "sabre/dav": "^4.3.1"
}, },
"type": "library", "type": "library",
@ -3797,7 +3799,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/thephpleague/flysystem/issues", "issues": "https://github.com/thephpleague/flysystem/issues",
"source": "https://github.com/thephpleague/flysystem/tree/3.15.1" "source": "https://github.com/thephpleague/flysystem/tree/3.16.0"
}, },
"funding": [ "funding": [
{ {
@ -3809,20 +3811,20 @@
"type": "github" "type": "github"
} }
], ],
"time": "2023-05-04T09:04:26+00:00" "time": "2023-09-07T19:22:17+00:00"
}, },
{ {
"name": "league/flysystem-aws-s3-v3", "name": "league/flysystem-aws-s3-v3",
"version": "3.15.0", "version": "3.16.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git",
"reference": "d8de61ee10b6a607e7996cff388c5a3a663e8c8a" "reference": "ded9ba346bb01cb9cc4cc7f2743c2c0e14d18e1c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/d8de61ee10b6a607e7996cff388c5a3a663e8c8a", "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/ded9ba346bb01cb9cc4cc7f2743c2c0e14d18e1c",
"reference": "d8de61ee10b6a607e7996cff388c5a3a663e8c8a", "reference": "ded9ba346bb01cb9cc4cc7f2743c2c0e14d18e1c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3863,7 +3865,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/thephpleague/flysystem-aws-s3-v3/issues", "issues": "https://github.com/thephpleague/flysystem-aws-s3-v3/issues",
"source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.15.0" "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.16.0"
}, },
"funding": [ "funding": [
{ {
@ -3875,20 +3877,20 @@
"type": "github" "type": "github"
} }
], ],
"time": "2023-05-02T20:02:14+00:00" "time": "2023-08-30T10:14:57+00:00"
}, },
{ {
"name": "league/flysystem-local", "name": "league/flysystem-local",
"version": "3.15.0", "version": "3.16.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/thephpleague/flysystem-local.git", "url": "https://github.com/thephpleague/flysystem-local.git",
"reference": "543f64c397fefdf9cfeac443ffb6beff602796b3" "reference": "ec7383f25642e6fd4bb0c9554fc2311245391781"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/543f64c397fefdf9cfeac443ffb6beff602796b3", "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/ec7383f25642e6fd4bb0c9554fc2311245391781",
"reference": "543f64c397fefdf9cfeac443ffb6beff602796b3", "reference": "ec7383f25642e6fd4bb0c9554fc2311245391781",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3923,7 +3925,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/thephpleague/flysystem-local/issues", "issues": "https://github.com/thephpleague/flysystem-local/issues",
"source": "https://github.com/thephpleague/flysystem-local/tree/3.15.0" "source": "https://github.com/thephpleague/flysystem-local/tree/3.16.0"
}, },
"funding": [ "funding": [
{ {
@ -3935,7 +3937,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2023-05-02T20:02:14+00:00" "time": "2023-08-30T10:23:59+00:00"
}, },
{ {
"name": "league/mime-type-detection", "name": "league/mime-type-detection",
@ -4159,20 +4161,20 @@
}, },
{ {
"name": "league/uri", "name": "league/uri",
"version": "7.2.1", "version": "7.3.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/thephpleague/uri.git", "url": "https://github.com/thephpleague/uri.git",
"reference": "8b644f8ff80352530bbc0ea467d5b5a89b60d832" "reference": "36743c3961bb82bf93da91917b6bced0358a8d45"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/thephpleague/uri/zipball/8b644f8ff80352530bbc0ea467d5b5a89b60d832", "url": "https://api.github.com/repos/thephpleague/uri/zipball/36743c3961bb82bf93da91917b6bced0358a8d45",
"reference": "8b644f8ff80352530bbc0ea467d5b5a89b60d832", "reference": "36743c3961bb82bf93da91917b6bced0358a8d45",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"league/uri-interfaces": "^7.2", "league/uri-interfaces": "^7.3",
"php": "^8.1" "php": "^8.1"
}, },
"conflict": { "conflict": {
@ -4237,7 +4239,7 @@
"docs": "https://uri.thephpleague.com", "docs": "https://uri.thephpleague.com",
"forum": "https://thephpleague.slack.com", "forum": "https://thephpleague.slack.com",
"issues": "https://github.com/thephpleague/uri-src/issues", "issues": "https://github.com/thephpleague/uri-src/issues",
"source": "https://github.com/thephpleague/uri/tree/7.2.1" "source": "https://github.com/thephpleague/uri/tree/7.3.0"
}, },
"funding": [ "funding": [
{ {
@ -4245,20 +4247,20 @@
"type": "github" "type": "github"
} }
], ],
"time": "2023-08-30T21:06:57+00:00" "time": "2023-09-09T17:21:43+00:00"
}, },
{ {
"name": "league/uri-interfaces", "name": "league/uri-interfaces",
"version": "7.2.0", "version": "7.3.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/thephpleague/uri-interfaces.git", "url": "https://github.com/thephpleague/uri-interfaces.git",
"reference": "43fa071050fcba89aefb5d4789a4a5a73874c44b" "reference": "c409b60ed2245ff94c965a8c798a60166db53361"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/43fa071050fcba89aefb5d4789a4a5a73874c44b", "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/c409b60ed2245ff94c965a8c798a60166db53361",
"reference": "43fa071050fcba89aefb5d4789a4a5a73874c44b", "reference": "c409b60ed2245ff94c965a8c798a60166db53361",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -4321,7 +4323,7 @@
"docs": "https://uri.thephpleague.com", "docs": "https://uri.thephpleague.com",
"forum": "https://thephpleague.slack.com", "forum": "https://thephpleague.slack.com",
"issues": "https://github.com/thephpleague/uri-src/issues", "issues": "https://github.com/thephpleague/uri-src/issues",
"source": "https://github.com/thephpleague/uri-interfaces/tree/7.2.0" "source": "https://github.com/thephpleague/uri-interfaces/tree/7.3.0"
}, },
"funding": [ "funding": [
{ {
@ -4329,7 +4331,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2023-08-30T19:43:38+00:00" "time": "2023-09-09T17:21:43+00:00"
}, },
{ {
"name": "livewire/livewire", "name": "livewire/livewire",
@ -6079,16 +6081,16 @@
}, },
{ {
"name": "phpstan/phpdoc-parser", "name": "phpstan/phpdoc-parser",
"version": "1.23.1", "version": "1.24.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git", "url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "846ae76eef31c6d7790fac9bc399ecee45160b26" "reference": "3510b0a6274cc42f7219367cb3abfc123ffa09d6"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/846ae76eef31c6d7790fac9bc399ecee45160b26", "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/3510b0a6274cc42f7219367cb3abfc123ffa09d6",
"reference": "846ae76eef31c6d7790fac9bc399ecee45160b26", "reference": "3510b0a6274cc42f7219367cb3abfc123ffa09d6",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -6120,9 +6122,9 @@
"description": "PHPDoc parser with support for nullable, intersection and generic types", "description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": { "support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues", "issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.23.1" "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.0"
}, },
"time": "2023-08-03T16:32:59+00:00" "time": "2023-09-07T20:46:32+00:00"
}, },
{ {
"name": "pragmarx/google2fa", "name": "pragmarx/google2fa",
@ -12405,16 +12407,16 @@
}, },
{ {
"name": "friendsofphp/php-cs-fixer", "name": "friendsofphp/php-cs-fixer",
"version": "v3.25.1", "version": "v3.26.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "8e21d69801de6b5ecb0dbe0bcdf967b335b1260b" "reference": "d023ba6684055f6ea1da1352d8a02baca0426983"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/8e21d69801de6b5ecb0dbe0bcdf967b335b1260b", "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/d023ba6684055f6ea1da1352d8a02baca0426983",
"reference": "8e21d69801de6b5ecb0dbe0bcdf967b335b1260b", "reference": "d023ba6684055f6ea1da1352d8a02baca0426983",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -12488,7 +12490,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.25.1" "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.26.1"
}, },
"funding": [ "funding": [
{ {
@ -12496,7 +12498,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2023-09-04T01:22:52+00:00" "time": "2023-09-08T19:09:07+00:00"
}, },
{ {
"name": "hamcrest/hamcrest-php", "name": "hamcrest/hamcrest-php",

View file

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddMinAmtToModelsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('models', function (Blueprint $table) {
$table->integer('min_amt')->after('model_number')->default(null);;
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('models', function (Blueprint $table) {
$table->dropColumn('min_amt');
});
}
}

View file

@ -210,10 +210,15 @@
</td> </td>
<td> <td>
@if ($file->filename) @if ($file->filename)
<a href="{{ route('show.accessoryfile', [$accessory->id, $file->id, 'download' => 'true']) }}" class="btn btn-default"> <a href="{{ route('show.accessoryfile', [$accessory->id, $file->id]) }}" class="btn btn-sm btn-default">
<i class="fas fa-download" aria-hidden="true"></i> <i class="fas fa-download" aria-hidden="true"></i>
<span class="sr-only">{{ trans('general.download') }}</span> <span class="sr-only">{{ trans('general.download') }}</span>
</a> </a>
<a href="{{ route('show.accessoryfile', [$accessory->id, $file->id, 'inline' => 'true']) }}" class="btn btn-sm btn-default" target="_blank">
<i class="fa fa-external-link" aria-hidden="true"></i>
</a>
@endif @endif
</td> </td>
<td>{{ $file->created_at }}</td> <td>{{ $file->created_at }}</td>

View file

@ -203,10 +203,15 @@
</td> </td>
<td> <td>
@if ($file->filename) @if ($file->filename)
<a href="{{ route('show.componentfile', [$component->id, $file->id, 'download' => 'true']) }}" class="btn btn-default"> <a href="{{ route('show.componentfile', [$component->id, $file->id]) }}" class="btn btn-sm btn-default">
<i class="fas fa-download" aria-hidden="true"></i> <i class="fas fa-download" aria-hidden="true"></i>
<span class="sr-only">{{ trans('general.download') }}</span> <span class="sr-only">{{ trans('general.download') }}</span>
</a> </a>
<a href="{{ route('show.componentfile', [$component->id, $file->id, 'inline' => 'true']) }}" class="btn btn-sm btn-default" target="_blank">
<i class="fa fa-external-link" aria-hidden="true"></i>
</a>
@endif @endif
</td> </td>
<td>{{ $file->created_at }}</td> <td>{{ $file->created_at }}</td>

View file

@ -160,10 +160,14 @@
</td> </td>
<td> <td>
@if ($file->filename) @if ($file->filename)
<a href="{{ route('show.consumablefile', [$consumable->id, $file->id, 'download' => 'true']) }}" class="btn btn-default"> <a href="{{ route('show.consumablefile', [$consumable->id, $file->id]) }}" class="btn btn-sm btn-default">
<i class="fas fa-download" aria-hidden="true"></i> <i class="fas fa-download" aria-hidden="true"></i>
<span class="sr-only">{{ trans('general.download') }}</span> <span class="sr-only">{{ trans('general.download') }}</span>
</a> </a>
<a href="{{ route('show.consumablefile', [$consumable->id, $file->id, 'inline' => 'true']) }}" class="btn btn-sm btn-default" target="_blank">
<i class="fa fa-external-link" aria-hidden="true"></i>
</a>
@endif @endif
</td> </td>
<td>{{ $file->created_at }}</td> <td>{{ $file->created_at }}</td>

View file

@ -1266,9 +1266,13 @@
</td> </td>
<td> <td>
@if (($file->filename) && (Storage::exists('private_uploads/assets/'.$file->filename))) @if (($file->filename) && (Storage::exists('private_uploads/assets/'.$file->filename)))
<a href="{{ route('show/assetfile', [$asset->id, $file->id]) }}" class="btn btn-default"> <a href="{{ route('show/assetfile', [$asset->id, $file->id, 'download'=>'true']) }}" class="btn btn-sm btn-default">
<i class="fas fa-download" aria-hidden="true"></i> <i class="fas fa-download" aria-hidden="true"></i>
</a> </a>
<a href="{{ route('show/assetfile', [$asset->id, $file->id, 'inline'=>'true']) }}" class="btn btn-sm btn-default" target="_blank">
<i class="fa fa-external-link" aria-hidden="true"></i>
</a>
@endif @endif
</td> </td>
<td> <td>
@ -1363,9 +1367,14 @@
</td> </td>
<td> <td>
@if (($file->filename) && (Storage::exists('private_uploads/assetmodels/'.$file->filename))) @if (($file->filename) && (Storage::exists('private_uploads/assetmodels/'.$file->filename)))
<a href="{{ route('show/modelfile', [$asset->model->id, $file->id]) }}" class="btn btn-default"> <a href="{{ route('show/modelfile', [$asset->model->id, $file->id]) }}" class="btn btn-sm btn-default">
<i class="fas fa-download" aria-hidden="true"></i> <i class="fas fa-download" aria-hidden="true"></i>
</a> </a>
<a href="{{ route('show/modelfile', [$asset->model->id, $file->id, 'inline'=>'true']) }}" class="btn btn-sm btn-default" target="_blank">
<i class="fa fa-external-link" aria-hidden="true"></i>
</a>
@endif @endif
</td> </td>
<td> <td>

View file

@ -474,10 +474,15 @@
</td> </td>
<td> <td>
@if ($file->filename) @if ($file->filename)
<a href="{{ route('show.licensefile', [$license->id, $file->id, 'download' => 'true']) }}" class="btn btn-default"> <a href="{{ route('show.licensefile', [$license->id, $file->id]) }}" class="btn btn-sm btn-default">
<i class="fas fa-download" aria-hidden="true"></i> <i class="fas fa-download" aria-hidden="true"></i>
<span class="sr-only">{{ trans('general.download') }}</span> <span class="sr-only">{{ trans('general.download') }}</span>
</a> </a>
<a href="{{ route('show.licensefile', [$license->id, $file->id, 'inline' => 'true']) }}" class="btn btn-sm btn-default" target="_blank">
<i class="fa fa-external-link" aria-hidden="true"></i>
</a>
@endif @endif
</td> </td>
<td>{{ $file->created_at }}</td> <td>{{ $file->created_at }}</td>

View file

@ -15,6 +15,7 @@
@include ('partials.forms.edit.manufacturer-select', ['translated_name' => trans('general.manufacturer'), 'fieldname' => 'manufacturer_id']) @include ('partials.forms.edit.manufacturer-select', ['translated_name' => trans('general.manufacturer'), 'fieldname' => 'manufacturer_id'])
@include ('partials.forms.edit.model_number') @include ('partials.forms.edit.model_number')
@include ('partials.forms.edit.depreciation') @include ('partials.forms.edit.depreciation')
@include ('partials.forms.edit.minimum_quantity')
<!-- EOL --> <!-- EOL -->

View file

@ -168,9 +168,14 @@
</td> </td>
<td> <td>
@if (($file->filename) && (Storage::exists('private_uploads/assetmodels/'.$file->filename))) @if (($file->filename) && (Storage::exists('private_uploads/assetmodels/'.$file->filename)))
<a href="{{ route('show/modelfile', [$model->id, $file->id]) }}" class="btn btn-default"> <a href="{{ route('show/modelfile', [$model->id, $file->id]) }}" class="btn btn-sm btn-default">
<i class="fas fa-download" aria-hidden="true"></i> <i class="fas fa-download" aria-hidden="true"></i>
</a> </a>
<a href="{{ route('show/modelfile', [$model->id, $file->id, 'inline'=>'true']) }}" class="btn btn-sm btn-default" target="_blank">
<i class="fa fa-external-link" aria-hidden="true"></i>
</a>
@endif @endif
</td> </td>
<td> <td>

View file

@ -913,7 +913,7 @@
<td> <td>
@if (($file->filename) && (Storage::exists('private_uploads/users/'.$file->filename))) @if (($file->filename) && (Storage::exists('private_uploads/users/'.$file->filename)))
@if (Helper::checkUploadIsImage($file->get_src('users'))) @if (Helper::checkUploadIsImage($file->get_src('users')))
<a href="{{ route('show/userfile', ['userId' => $user->id, 'fileId' => $file->id, 'download' => 'false']) }}" data-toggle="lightbox" data-type="image"><img src="{{ route('show/userfile', ['userId' => $user->id, 'fileId' => $file->id]) }}" class="img-thumbnail" style="max-width: 50px;"></a> <a href="{{ route('show/userfile', [$user->id, $file->id, 'inline' => 'true']) }}" data-toggle="lightbox" data-type="image"><img src="{{ route('show/userfile', [$user->id, $file->id, 'inline' => 'true']) }}" class="img-thumbnail" style="max-width: 50px;"></a>
@else @else
{{ trans('general.preview_not_available') }} {{ trans('general.preview_not_available') }}
@endif @endif
@ -937,10 +937,14 @@
<td> <td>
@if ($file->filename) @if ($file->filename)
@if (Storage::exists('private_uploads/users/'.$file->filename)) @if (Storage::exists('private_uploads/users/'.$file->filename))
<a href="{{ route('show/userfile', [$user->id, $file->id]) }}" class="btn btn-default"> <a href="{{ route('show/userfile', [$user->id, $file->id]) }}" class="btn btn-sm btn-default">
<i class="fas fa-download" aria-hidden="true"></i> <i class="fas fa-download" aria-hidden="true"></i>
<span class="sr-only">{{ trans('general.download') }}</span> <span class="sr-only">{{ trans('general.download') }}</span>
</a> </a>
<a href="{{ route('show/userfile', [$user->id, $file->id, 'inline' => 'true']) }}" class="btn btn-sm btn-default" target="_blank">
<i class="fa fa-external-link" aria-hidden="true"></i>
</a>
@endif @endif
@endif @endif
</td> </td>

View file

@ -0,0 +1,87 @@
<?php
namespace Tests\Feature\Api\Users;
use App\Models\Company;
use App\Models\Department;
use App\Models\Group;
use App\Models\Location;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Tests\Support\InteractsWithSettings;
use Tests\TestCase;
class UsersUpdateTest extends TestCase
{
use InteractsWithSettings;
public function testCanUpdateUserViaPatch()
{
$admin = User::factory()->superuser()->create();
$manager = User::factory()->create();
$company = Company::factory()->create();
$department = Department::factory()->create();
$location = Location::factory()->create();
[$groupA, $groupB] = Group::factory()->count(2)->create();
$user = User::factory()->create([
'activated' => false,
'remote' => false,
'vip' => false,
]);
$this->actingAsForApi($admin)
->patchJson(route('api.users.update', $user), [
'first_name' => 'Mabel',
'last_name' => 'Mora',
'username' => 'mabel',
'password' => 'super-secret',
'email' => 'mabel@onlymurderspod.com',
'permissions' => '{"a.new.permission":"1"}',
'activated' => true,
'phone' => '619-555-5555',
'jobtitle' => 'Host',
'manager_id' => $manager->id,
'employee_num' => '1111',
'notes' => 'Pretty good artist',
'company_id' => $company->id,
'department_id' => $department->id,
'location_id' => $location->id,
'remote' => true,
'groups' => $groupA->id,
'vip' => true,
'start_date' => '2021-08-01',
'end_date' => '2025-12-31',
])
->assertOk();
$user->refresh();
$this->assertEquals('Mabel', $user->first_name, 'First name was not updated');
$this->assertEquals('Mora', $user->last_name, 'Last name was not updated');
$this->assertEquals('mabel', $user->username, 'Username was not updated');
$this->assertTrue(Hash::check('super-secret', $user->password), 'Password was not updated');
$this->assertEquals('mabel@onlymurderspod.com', $user->email, 'Email was not updated');
$this->assertArrayHasKey('a.new.permission', $user->decodePermissions(), 'Permissions were not updated');
$this->assertTrue((bool)$user->activated, 'User not marked as activated');
$this->assertEquals('619-555-5555', $user->phone, 'Phone was not updated');
$this->assertEquals('Host', $user->jobtitle, 'Job title was not updated');
$this->assertTrue($user->manager->is($manager), 'Manager was not updated');
$this->assertEquals('1111', $user->employee_num, 'Employee number was not updated');
$this->assertEquals('Pretty good artist', $user->notes, 'Notes was not updated');
$this->assertTrue($user->company->is($company), 'Company was not updated');
$this->assertTrue($user->department->is($department), 'Department was not updated');
$this->assertTrue($user->location->is($location), 'Location was not updated');
$this->assertEquals(1, $user->remote, 'Remote was not updated');
$this->assertTrue($user->groups->contains($groupA), 'Groups were not updated');
$this->assertEquals(1, $user->vip, 'VIP was not updated');
$this->assertEquals('2021-08-01', $user->start_date, 'Start date was not updated');
$this->assertEquals('2025-12-31', $user->end_date, 'End date was not updated');
// `groups` can be an id or array or ids
$this->patch(route('api.users.update', $user), ['groups' => [$groupA->id, $groupB->id]]);
$user->refresh();
$this->assertTrue($user->groups->contains($groupA), 'Not part of expected group');
$this->assertTrue($user->groups->contains($groupB), 'Not part of expected group');
}
}