Merge pull request #17539 from grokability/add-file-uploads-to-maintenances
WIP: Add file uploads to maintenances
This commit is contained in:
@@ -242,6 +242,7 @@ class RestoreFromBackup extends Command
|
||||
|
||||
$private_dirs = [
|
||||
'storage/private_uploads/accessories',
|
||||
'storage/private_uploads/asset_maintenances',
|
||||
'storage/private_uploads/assetmodels',
|
||||
'storage/private_uploads/assets', // these are asset _files_, not the pictures.
|
||||
'storage/private_uploads/audits',
|
||||
@@ -260,9 +261,9 @@ class RestoreFromBackup extends Command
|
||||
];
|
||||
$public_dirs = [
|
||||
'public/uploads/accessories',
|
||||
'public/uploads/asset_maintenances',
|
||||
'public/uploads/assets', // these are asset _pictures_, not asset files
|
||||
'public/uploads/avatars',
|
||||
//'public/uploads/barcodes', // we don't want this, let the barcodes be regenerated
|
||||
'public/uploads/categories',
|
||||
'public/uploads/companies',
|
||||
'public/uploads/components',
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Accessories;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Accessory;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use \Illuminate\Contracts\View\View;
|
||||
use \Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
||||
class AccessoriesFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Validates and stores files associated with a accessory.
|
||||
*
|
||||
* @param UploadFileRequest $request
|
||||
* @param int $accessoryId
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @todo Switch to using the AssetFileRequest form request validator.
|
||||
*/
|
||||
public function store(UploadFileRequest $request, $accessoryId = null) : RedirectResponse
|
||||
{
|
||||
|
||||
if (config('app.lock_passwords')) {
|
||||
return redirect()->route('accessories.show', ['accessory'=>$accessoryId])->with('error', trans('general.feature_disabled'));
|
||||
}
|
||||
|
||||
$accessory = Accessory::find($accessoryId);
|
||||
|
||||
if (isset($accessory->id)) {
|
||||
$this->authorize('accessories.files', $accessory);
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
if (! Storage::exists('private_uploads/accessories')) {
|
||||
Storage::makeDirectory('private_uploads/accessories', 775);
|
||||
}
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
|
||||
$file_name = $request->handleFile('private_uploads/accessories/', 'accessory-'.$accessory->id, $file);
|
||||
//Log the upload to the log
|
||||
$accessory->logUpload($file_name, e($request->input('notes')));
|
||||
}
|
||||
|
||||
|
||||
return redirect()->route('accessories.show', $accessory->id)->withFragment('files')->with('success', trans('general.file_upload_success'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('accessories.show', $accessory->id)->withFragment('files')->with('error', trans('general.no_files_uploaded'));
|
||||
}
|
||||
// Prepare the error message
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the selected accessory file.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $accessoryId
|
||||
* @param int $fileId
|
||||
*/
|
||||
public function destroy($accessoryId = null, $fileId = null) : RedirectResponse
|
||||
{
|
||||
if ($accessory = Accessory::find($accessoryId)) {
|
||||
$this->authorize('update', $accessory);
|
||||
|
||||
if ($log = Actionlog::find($fileId)) {
|
||||
|
||||
if (Storage::exists('private_uploads/accessories/'.$log->filename)) {
|
||||
try {
|
||||
Storage::delete('private_uploads/accessories/' . $log->filename);
|
||||
$log->delete();
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
} catch (\Exception $e) {
|
||||
Log::debug($e);
|
||||
return redirect()->route('accessories.index')->with('error', trans('general.file_does_not_exist'));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return redirect()->route('accessories.show', ['accessory' => $accessory])->withFragment('files')->with('error', trans('general.log_record_not_found'));
|
||||
}
|
||||
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the selected file to be viewed.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.4]
|
||||
* @param int $accessoryId
|
||||
* @param int $fileId
|
||||
*/
|
||||
public function show($accessoryId = null, $fileId = null) : View | RedirectResponse | Response | BinaryFileResponse | StreamedResponse
|
||||
{
|
||||
|
||||
|
||||
// the accessory is valid
|
||||
if ($accessory = Accessory::find($accessoryId)) {
|
||||
$this->authorize('view', $accessory);
|
||||
$this->authorize('accessories.files', $accessory);
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $accessory->id)->find($fileId)) {
|
||||
$file = 'private_uploads/accessories/'.$log->filename;
|
||||
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('accessories.show', ['accessory' => $accessory])->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->route('accessories.show', ['accessory' => $accessory])->withFragment('files')->with('error', trans('general.log_record_not_found'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ use App\Http\Transformers\UploadedFilesTransformer;
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetMaintenance;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Component;
|
||||
use App\Models\Consumable;
|
||||
@@ -27,9 +28,9 @@ use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
class UploadedFilesController extends Controller
|
||||
{
|
||||
|
||||
|
||||
static $map_object_type = [
|
||||
'accessories' => Accessory::class,
|
||||
'maintenances' => AssetMaintenance::class,
|
||||
'assets' => Asset::class,
|
||||
'components' => Component::class,
|
||||
'consumables' => Consumable::class,
|
||||
@@ -42,6 +43,7 @@ class UploadedFilesController extends Controller
|
||||
|
||||
static $map_storage_path = [
|
||||
'accessories' => 'private_uploads/accessories/',
|
||||
'maintenances' => 'private_uploads/asset_maintenances/',
|
||||
'assets' => 'private_uploads/assets/',
|
||||
'components' => 'private_uploads/components/',
|
||||
'consumables' => 'private_uploads/consumables/',
|
||||
@@ -54,6 +56,7 @@ class UploadedFilesController extends Controller
|
||||
|
||||
static $map_file_prefix= [
|
||||
'accessories' => 'accessory',
|
||||
'maintenances' => 'maintenance',
|
||||
'assets' => 'asset',
|
||||
'components' => 'component',
|
||||
'consumables' => 'consumable',
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\AssetModel;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use \Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
|
||||
class AssetModelsFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Upload a file to the server.
|
||||
*
|
||||
* @param UploadFileRequest $request
|
||||
* @param int $modelId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*@since [v1.0]
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*/
|
||||
public function store(UploadFileRequest $request, $modelId = null) : RedirectResponse
|
||||
{
|
||||
if (! $model = AssetModel::find($modelId)) {
|
||||
return redirect()->route('models.index')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize('update', $model);
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
if (! Storage::exists('private_uploads/assetmodels')) {
|
||||
Storage::makeDirectory('private_uploads/assetmodels', 775);
|
||||
}
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
|
||||
$file_name = $request->handleFile('private_uploads/assetmodels/','model-'.$model->id,$file);
|
||||
|
||||
$model->logUpload($file_name, $request->get('notes'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('general.file_upload_success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('error', trans('admin/hardware/message.upload.nofiles'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for permissions and display the file.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $modelId
|
||||
* @param int $fileId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function show(AssetModel $model, $fileId = null) : StreamedResponse | Response | RedirectResponse | BinaryFileResponse
|
||||
{
|
||||
|
||||
$this->authorize('view', $model);
|
||||
|
||||
if (! $log = Actionlog::find($fileId)) {
|
||||
return response('No matching record for that model/file', 500)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
$file = 'private_uploads/assetmodels/'.$log->filename;
|
||||
|
||||
if (! Storage::exists($file)) {
|
||||
return response('File '.$file.' not found on server', 404)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
if (request('inline') == 'true') {
|
||||
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
|
||||
return Storage::download($file, $log->filename, $headers);
|
||||
}
|
||||
|
||||
return StorageHelper::downloader($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the associated file
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $modelId
|
||||
* @param int $fileId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function destroy(AssetModel $model, $fileId = null) : RedirectResponse
|
||||
{
|
||||
$rel_path = 'private_uploads/assetmodels';
|
||||
$this->authorize('update', $model);
|
||||
$log = Actionlog::find($fileId);
|
||||
if ($log) {
|
||||
if (Storage::exists($rel_path.'/'.$log->filename)) {
|
||||
Storage::delete($rel_path.'/'.$log->filename);
|
||||
}
|
||||
$log->delete();
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Assets;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use \Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use \Illuminate\Contracts\View\View;
|
||||
use \Illuminate\Http\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
|
||||
class AssetFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Upload a file to the server.
|
||||
*
|
||||
* @param UploadFileRequest $request
|
||||
* @param int $assetId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*@since [v1.0]
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*/
|
||||
public function store(UploadFileRequest $request, Asset $asset) : RedirectResponse
|
||||
{
|
||||
|
||||
$this->authorize('update', $asset);
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
if (! Storage::exists('private_uploads/assets')) {
|
||||
Storage::makeDirectory('private_uploads/assets', 775);
|
||||
}
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
$file_name = $request->handleFile('private_uploads/assets/','hardware-'.$asset->id, $file);
|
||||
|
||||
$asset->logUpload($file_name, $request->get('notes'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.upload.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->with('error', trans('admin/hardware/message.upload.nofiles'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for permissions and display the file.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @param int $fileId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function show(Asset $asset, $fileId = null) : View | RedirectResponse | Response | StreamedResponse | BinaryFileResponse
|
||||
{
|
||||
|
||||
$this->authorize('view', $asset);
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $asset->id)->find($fileId)) {
|
||||
$file = 'private_uploads/assets/'.$log->filename;
|
||||
|
||||
if ($log->action_type == 'audit') {
|
||||
$file = 'private_uploads/audits/'.$log->filename;
|
||||
}
|
||||
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('hardware.show', $asset)->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('hardware.show', $asset)->with('error', trans('general.log_record_not_found'));
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the associated file
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @param int $fileId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function destroy(Asset $asset, $fileId = null) : RedirectResponse
|
||||
{
|
||||
$this->authorize('update', $asset);
|
||||
$rel_path = 'private_uploads/assets';
|
||||
|
||||
if ($log = Actionlog::find($fileId)) {
|
||||
if (Storage::exists($rel_path.'/'.$log->filename)) {
|
||||
Storage::delete($rel_path.'/'.$log->filename);
|
||||
}
|
||||
$log->delete();
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
}
|
||||
|
||||
return redirect()->route('hardware.show', $asset)->with('error', trans('general.log_record_not_found'));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Components;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Component;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class ComponentsFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Validates and stores files associated with a component.
|
||||
*
|
||||
* @param UploadFileRequest $request
|
||||
* @param int $componentId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*@author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @todo Switch to using the AssetFileRequest form request validator.
|
||||
*/
|
||||
public function store(UploadFileRequest $request, $componentId = null)
|
||||
{
|
||||
|
||||
if (config('app.lock_passwords')) {
|
||||
return redirect()->route('components.show', ['component'=>$componentId])->with('error', trans('general.feature_disabled'));
|
||||
}
|
||||
|
||||
$component = Component::find($componentId);
|
||||
|
||||
if (isset($component->id)) {
|
||||
$this->authorize('update', $component);
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
if (! Storage::exists('private_uploads/components')) {
|
||||
Storage::makeDirectory('private_uploads/components', 775);
|
||||
}
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
$file_name = $request->handleFile('private_uploads/components/','component-'.$component->id, $file);
|
||||
|
||||
//Log the upload to the log
|
||||
$component->logUpload($file_name, e($request->input('notes')));
|
||||
}
|
||||
|
||||
|
||||
return redirect()->route('components.show', $component->id)->withFragment('files')->with('success', trans('general.file_upload_success'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('components.show', $component->id)->with('error', trans('general.no_files_uploaded'));
|
||||
}
|
||||
// Prepare the error message
|
||||
return redirect()->route('components.index')
|
||||
->with('error', trans('general.file_does_not_exist'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the selected component file.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $componentId
|
||||
* @param int $fileId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($componentId = null, $fileId = null)
|
||||
{
|
||||
$component = Component::find($componentId);
|
||||
|
||||
// the asset is valid
|
||||
if (isset($component->id)) {
|
||||
$this->authorize('update', $component);
|
||||
$log = Actionlog::find($fileId);
|
||||
|
||||
// Remove the file if one exists
|
||||
if (Storage::exists('components/'.$log->filename)) {
|
||||
try {
|
||||
Storage::delete('components/'.$log->filename);
|
||||
} catch (\Exception $e) {
|
||||
Log::debug($e);
|
||||
}
|
||||
}
|
||||
|
||||
$log->delete();
|
||||
|
||||
return redirect()->back()->withFragment('files')
|
||||
->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
}
|
||||
|
||||
// Redirect to the licence management page
|
||||
return redirect()->route('components.index')->with('error', trans('general.file_does_not_exist'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the selected file to be viewed.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.4]
|
||||
* @param int $componentId
|
||||
* @param int $fileId
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($componentId = null, $fileId = null)
|
||||
{
|
||||
Log::debug('Private filesystem is: '.config('filesystems.default'));
|
||||
|
||||
|
||||
// the component is valid
|
||||
if ($component = Component::find($componentId)) {
|
||||
$this->authorize('view', $component);
|
||||
$this->authorize('components.files', $component);
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $component->id)->find($fileId)) {
|
||||
|
||||
$file = 'private_uploads/components/'.$log->filename;
|
||||
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('components.show', ['component' => $component])->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
}
|
||||
return redirect()->route('components.show', ['component' => $component])->with('error', trans('general.log_record_not_found'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('components.index')->with('error', trans('general.file_does_not_exist', ['id' => $fileId]));
|
||||
}
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Consumables;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Consumable;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Symfony\Consumable\HttpFoundation\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
class ConsumablesFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Validates and stores files associated with a consumable.
|
||||
*
|
||||
* @param UploadFileRequest $request
|
||||
* @param int $consumableId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*@author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @todo Switch to using the AssetFileRequest form request validator.
|
||||
*/
|
||||
public function store(UploadFileRequest $request, $consumableId = null)
|
||||
{
|
||||
if (config('app.lock_passwords')) {
|
||||
return redirect()->route('consumables.show', ['consumable'=>$consumableId])->with('error', trans('general.feature_disabled'));
|
||||
}
|
||||
|
||||
$consumable = Consumable::find($consumableId);
|
||||
|
||||
if (isset($consumable->id)) {
|
||||
$this->authorize('update', $consumable);
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
if (! Storage::exists('private_uploads/consumables')) {
|
||||
Storage::makeDirectory('private_uploads/consumables', 775);
|
||||
}
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
$file_name = $request->handleFile('private_uploads/consumables/','consumable-'.$consumable->id, $file);
|
||||
|
||||
//Log the upload to the log
|
||||
$consumable->logUpload($file_name, e($request->input('notes')));
|
||||
}
|
||||
|
||||
|
||||
return redirect()->route('consumables.show', $consumable->id)->withFragment('files')->with('success', trans('general.file_upload_success'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('consumables.show', $consumable->id)->with('error', trans('general.no_files_uploaded'));
|
||||
}
|
||||
// Prepare the error message
|
||||
return redirect()->route('consumables.index')
|
||||
->with('error', trans('general.file_does_not_exist'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the selected consumable file.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $consumableId
|
||||
* @param int $fileId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($consumableId = null, $fileId = null)
|
||||
{
|
||||
$consumable = Consumable::find($consumableId);
|
||||
|
||||
// the asset is valid
|
||||
if (isset($consumable->id)) {
|
||||
$this->authorize('update', $consumable);
|
||||
$log = Actionlog::find($fileId);
|
||||
|
||||
// Remove the file if one exists
|
||||
if (Storage::exists('consumables/'.$log->filename)) {
|
||||
try {
|
||||
Storage::delete('consumables/'.$log->filename);
|
||||
} catch (\Exception $e) {
|
||||
Log::debug($e);
|
||||
}
|
||||
}
|
||||
|
||||
$log->delete();
|
||||
|
||||
return redirect()->back()->withFragment('files')
|
||||
->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
}
|
||||
|
||||
// Redirect to the licence management page
|
||||
return redirect()->route('consumables.index')->with('error', trans('general.file_does_not_exist'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the selected file to be viewed.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.4]
|
||||
* @param int $consumableId
|
||||
* @param int $fileId
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($consumableId = null, $fileId = null)
|
||||
{
|
||||
$consumable = Consumable::find($consumableId);
|
||||
|
||||
// the consumable is valid
|
||||
if (isset($consumable->id)) {
|
||||
$this->authorize('view', $consumable);
|
||||
$this->authorize('consumables.files', $consumable);
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $consumable->id)->find($fileId)) {
|
||||
$file = 'private_uploads/consumables/'.$log->filename;
|
||||
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('consumables.show', ['consumable' => $consumable])->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
}
|
||||
// The log record doesn't exist somehow
|
||||
return redirect()->route('consumables.show', ['consumable' => $consumable])->with('error', trans('general.log_record_not_found'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('consumables.index')->with('error', trans('general.file_does_not_exist', ['id' => $fileId]));
|
||||
}
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Licenses;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\License;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class LicenseFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Validates and stores files associated with a license.
|
||||
*
|
||||
* @param UploadFileRequest $request
|
||||
* @param int $licenseId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @todo Switch to using the AssetFileRequest form request validator.
|
||||
*/
|
||||
public function store(UploadFileRequest $request, $licenseId = null)
|
||||
{
|
||||
$license = License::find($licenseId);
|
||||
|
||||
if (isset($license->id)) {
|
||||
$this->authorize('update', $license);
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
if (! Storage::exists('private_uploads/licenses')) {
|
||||
Storage::makeDirectory('private_uploads/licenses', 775);
|
||||
}
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
$file_name = $request->handleFile('private_uploads/licenses/','license-'.$license->id, $file);
|
||||
|
||||
//Log the upload to the log
|
||||
$license->logUpload($file_name, e($request->input('notes')));
|
||||
}
|
||||
|
||||
|
||||
return redirect()->route('licenses.show', $license->id)->with('success', trans('admin/licenses/message.upload.success'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('licenses.show', $license->id)->with('error', trans('admin/licenses/message.upload.nofiles'));
|
||||
}
|
||||
// Prepare the error message
|
||||
return redirect()->route('licenses.index')
|
||||
->with('error', trans('admin/licenses/message.does_not_exist'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the selected license file.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $licenseId
|
||||
* @param int $fileId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($licenseId = null, $fileId = null)
|
||||
{
|
||||
if ($license = License::find($licenseId)) {
|
||||
|
||||
$this->authorize('update', $license);
|
||||
|
||||
if ($log = Actionlog::find($fileId)) {
|
||||
|
||||
// Remove the file if one exists
|
||||
if (Storage::exists('licenses/'.$log->filename)) {
|
||||
try {
|
||||
Storage::delete('licenses/'.$log->filename);
|
||||
} catch (\Exception $e) {
|
||||
Log::debug($e);
|
||||
}
|
||||
}
|
||||
|
||||
$log->delete();
|
||||
|
||||
return redirect()->back()
|
||||
->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
}
|
||||
|
||||
return redirect()->route('licenses.index')->with('error', trans('general.log_does_not_exist'));
|
||||
}
|
||||
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the selected file to be viewed.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.4]
|
||||
* @param int $licenseId
|
||||
* @param int $fileId
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($licenseId = null, $fileId = null, $download = true)
|
||||
{
|
||||
$license = License::find($licenseId);
|
||||
|
||||
// the license is valid
|
||||
if (isset($license->id)) {
|
||||
$this->authorize('view', $license);
|
||||
$this->authorize('licenses.files', $license);
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $license->id)->find($fileId)) {
|
||||
$file = 'private_uploads/licenses/'.$log->filename;
|
||||
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('licenses.show', ['licenses' => $license])->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
}
|
||||
|
||||
// The log record doesn't exist somehow
|
||||
return redirect()->route('licenses.show', ['licenses' => $license])->with('error', trans('general.log_record_not_found'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist', ['id' => $fileId]));
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Location;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use \Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
|
||||
class LocationsFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Upload a file to the server.
|
||||
*
|
||||
* @param UploadFileRequest $request
|
||||
* @param int $modelId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*@since [v1.0]
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*/
|
||||
public function store(UploadFileRequest $request, Location $location) : RedirectResponse
|
||||
{
|
||||
$this->authorize('update', $location);
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
|
||||
if (! Storage::exists('private_uploads/locations')) {
|
||||
Storage::makeDirectory('private_uploads/locations', 775);
|
||||
}
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
$file_name = $request->handleFile('private_uploads/locations/','location-'.$location->id, $file);
|
||||
$location->logUpload($file_name, $request->get('notes'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('general.file_upload_success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('error', trans('admin/hardware/message.upload.nofiles'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for permissions and display the file.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $modelId
|
||||
* @param int $fileId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function show(Location $location, $fileId = null) : StreamedResponse | Response | RedirectResponse | BinaryFileResponse
|
||||
{
|
||||
|
||||
$this->authorize('view', $location);
|
||||
|
||||
if (! $log = Actionlog::find($fileId)) {
|
||||
return redirect()->back()->withFragment('files')->with('error', 'No matching file record');
|
||||
}
|
||||
|
||||
$file = 'private_uploads/locations/'.$log->filename;
|
||||
|
||||
if (! Storage::exists($file)) {
|
||||
return redirect()->back()->withFragment('files')->with('error', 'No matching file on server');
|
||||
}
|
||||
|
||||
if (request('inline') == 'true') {
|
||||
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
|
||||
return Storage::download($file, $log->filename, $headers);
|
||||
}
|
||||
|
||||
return StorageHelper::downloader($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the associated file
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $modelId
|
||||
* @param int $fileId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function destroy(Location $location, $fileId = null) : RedirectResponse
|
||||
{
|
||||
$rel_path = 'private_uploads/locations';
|
||||
$this->authorize('update', $location);
|
||||
$log = Actionlog::find($fileId);
|
||||
|
||||
if ($log) {
|
||||
|
||||
// This should be moved to purge
|
||||
// if (Storage::exists($rel_path.'/'.$log->filename)) {
|
||||
// Storage::delete($rel_path.'/'.$log->filename);
|
||||
// }
|
||||
$log->delete();
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -17,13 +17,11 @@ use App\Models\Depreciation;
|
||||
use App\Models\License;
|
||||
use App\Models\ReportTemplate;
|
||||
use App\Models\Setting;
|
||||
use App\Notifications\CheckoutAssetNotification;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use \Illuminate\Contracts\View\View;
|
||||
use League\Csv\Reader;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Models\Supplier;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use \Illuminate\Contracts\View\View;
|
||||
|
||||
|
||||
209
app/Http/Controllers/UploadedFilesController.php
Normal file
209
app/Http/Controllers/UploadedFilesController.php
Normal file
@@ -0,0 +1,209 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetMaintenance;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Component;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\License;
|
||||
use App\Models\Location;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
||||
/**
|
||||
* This controller provide the health route for
|
||||
* the Snipe-IT Asset Management application.
|
||||
*
|
||||
* @version v1.0
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
|
||||
*/
|
||||
class UploadedFilesController extends Controller
|
||||
{
|
||||
|
||||
static $map_object_type = [
|
||||
'accessories' => Accessory::class,
|
||||
'maintenances' => AssetMaintenance::class,
|
||||
'assets' => Asset::class,
|
||||
'components' => Component::class,
|
||||
'consumables' => Consumable::class,
|
||||
'hardware' => Asset::class,
|
||||
'licenses' => License::class,
|
||||
'locations' => Location::class,
|
||||
'models' => AssetModel::class,
|
||||
'users' => User::class,
|
||||
];
|
||||
|
||||
static $map_storage_path = [
|
||||
'accessories' => 'private_uploads/accessories/',
|
||||
'maintenances' => 'private_uploads/asset_maintenances/',
|
||||
'assets' => 'private_uploads/assets/',
|
||||
'components' => 'private_uploads/components/',
|
||||
'consumables' => 'private_uploads/consumables/',
|
||||
'hardware' => 'private_uploads/assets/',
|
||||
'licenses' => 'private_uploads/licenses/',
|
||||
'locations' => 'private_uploads/locations/',
|
||||
'models' => 'private_uploads/assetmodels/',
|
||||
'users' => 'private_uploads/users/',
|
||||
];
|
||||
|
||||
static $map_file_prefix= [
|
||||
'accessories' => 'accessory',
|
||||
'maintenances' => 'maintenance',
|
||||
'assets' => 'asset',
|
||||
'components' => 'component',
|
||||
'consumables' => 'consumable',
|
||||
'hardware' => 'asset',
|
||||
'licenses' => 'license',
|
||||
'locations' => 'location',
|
||||
'models' => 'model',
|
||||
'users' => 'user',
|
||||
];
|
||||
|
||||
/**
|
||||
* Accepts a POST to upload a file to the server.
|
||||
*
|
||||
* @param \App\Http\Requests\UploadFileRequest $request
|
||||
* @param string $object_type the type of object to upload the file to
|
||||
* @param int $id the ID of the object to store so we can check permisisons
|
||||
* @since [v8.2.2]
|
||||
* @author [A. Gianotto <snipe@snipe.net>]
|
||||
*/
|
||||
public function store(UploadFileRequest $request, $object_type, $id) : RedirectResponse
|
||||
{
|
||||
|
||||
// Check the permissions to make sure the user can view the object
|
||||
$object = self::$map_object_type[$object_type]::find($id);
|
||||
$this->authorize('update', $object);
|
||||
|
||||
if (!$object) {
|
||||
return redirect()->back()->withFragment('files')->with('error',trans('general.file_upload_status.invalid_object'));
|
||||
}
|
||||
|
||||
// If the file storage directory doesn't exist, create it
|
||||
if (! Storage::exists(self::$map_storage_path[$object_type])) {
|
||||
Storage::makeDirectory(self::$map_storage_path[$object_type], 775);
|
||||
}
|
||||
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
// Loop over the attached files and add them to the object
|
||||
foreach ($request->file('file') as $file) {
|
||||
$file_name = $request->handleFile(self::$map_storage_path[$object_type], self::$map_file_prefix[$object_type].'-'.$object->id, $file);
|
||||
$files[] = $file_name;
|
||||
$object->logUpload($file_name, $request->get('notes'));
|
||||
}
|
||||
|
||||
$files = Actionlog::select('action_logs.*')->where('action_type', '=', 'uploaded')
|
||||
->where('item_type', '=', self::$map_object_type[$object_type])
|
||||
->where('item_id', '=', $id)->whereIn('filename', $files)
|
||||
->get();
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('success', trans_choice('general.file_upload_status.upload.success', count($files)));
|
||||
}
|
||||
|
||||
// No files were submitted
|
||||
return redirect()->back()->withFragment('files')->with('error', trans('general.file_upload_status.nofiles'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Check for permissions and display the file.
|
||||
* This isn't currently used, but is here for future use.
|
||||
*
|
||||
* @param \App\Http\Requests\UploadFileRequest $request
|
||||
* @param string $object_type the type of object to upload the file to
|
||||
* @param int $id the ID of the object to delete from so we can check permisisons
|
||||
* @param $file_id the ID of the file to show from the action_logs table
|
||||
* @since [v8.2.2]
|
||||
* @author [A. Gianotto <snipe@snipe.net>]
|
||||
*/
|
||||
public function show($object_type, $id, $file_id) : RedirectResponse | StreamedResponse | Storage | StorageHelper | BinaryFileResponse
|
||||
{
|
||||
// Check the permissions to make sure the user can view the object
|
||||
$object = self::$map_object_type[$object_type]::find($id);
|
||||
$this->authorize('view', $object);
|
||||
|
||||
if (!$object) {
|
||||
return redirect()->back()->withFragment('files')->with('error',trans('general.file_upload_status.invalid_object'));
|
||||
}
|
||||
|
||||
|
||||
// Check that the file being requested exists for the object
|
||||
if (! $log = Actionlog::whereNotNull('filename')->where('item_type', self::$map_object_type[$object_type])->where('item_id', $object->id)->find($file_id))
|
||||
{
|
||||
return redirect()->back()->withFragment('files')->with('error', trans('general.file_upload_status.invalid_id'));
|
||||
}
|
||||
|
||||
|
||||
if (! Storage::exists(self::$map_storage_path[$object_type].'/'.$log->filename))
|
||||
{
|
||||
return redirect()->back()->withFragment('files')->with('error', trans('general.file_upload_status.file_not_found'));
|
||||
}
|
||||
|
||||
if (request('inline') == 'true') {
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
return Storage::download(self::$map_storage_path[$object_type].'/'.$log->filename, $log->filename, $headers);
|
||||
}
|
||||
|
||||
return StorageHelper::downloader(self::$map_storage_path[$object_type].'/'.$log->filename);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the associated file
|
||||
*
|
||||
* @param \App\Http\Requests\UploadFileRequest $request
|
||||
* @param string $object_type the type of object to upload the file to
|
||||
* @param int $id the ID of the object to delete from so we can check permisisons
|
||||
* @param $file_id the ID of the file to delete from the action_logs table
|
||||
* @since [v8.2.2]
|
||||
* @author [A. Gianotto <snipe@snipe.net>]
|
||||
*/
|
||||
public function destroy($object_type, $id, $file_id) : RedirectResponse
|
||||
{
|
||||
|
||||
// Check the permissions to make sure the user can view the object
|
||||
$object = self::$map_object_type[$object_type]::find($id);
|
||||
$this->authorize('update', self::$map_object_type[$object_type]);
|
||||
|
||||
if (!$object) {
|
||||
return redirect()->back()->withFragment('files')->with('error',trans('general.file_upload_status.invalid_object'));
|
||||
}
|
||||
|
||||
|
||||
// Check for the file
|
||||
$log = Actionlog::find($file_id)->where('item_type', self::$map_object_type[$object_type])
|
||||
->where('item_id', $object->id)->first();
|
||||
|
||||
if ($log) {
|
||||
// Check the file actually exists, and delete it
|
||||
if (Storage::exists(self::$map_storage_path[$object_type].'/'.$log->filename)) {
|
||||
Storage::delete(self::$map_storage_path[$object_type].'/'.$log->filename);
|
||||
}
|
||||
// Delete the record of the file
|
||||
if ($log->delete()) {
|
||||
return redirect()->back()->withFragment('files')->with('success', trans_choice('general.file_upload_status.delete.success', 1));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// The file doesn't seem to really exist, so report an error
|
||||
return redirect()->back()->withFragment('files')->with('success', trans_choice('general.file_upload_status.delete.error', 1));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Users;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\User;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class UserFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Return JSON response with a list of user details for the getIndex() view.
|
||||
*
|
||||
* @param UploadFileRequest $request
|
||||
* @param int $userId
|
||||
* @return string JSON
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*@author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.6]
|
||||
*/
|
||||
public function store(UploadFileRequest $request, User $user)
|
||||
{
|
||||
$this->authorize('update', $user);
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
if (! Storage::exists('private_uploads/users')) {
|
||||
Storage::makeDirectory('private_uploads/users', 775);
|
||||
}
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
$file_name = $request->handleFile('private_uploads/users/','user-'.$user->id, $file);
|
||||
$user->logUpload($file_name, $request->get('notes'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/users/message.upload.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->with('error', trans('admin/users/message.upload.nofiles'));
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete file
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.6]
|
||||
* @param int $userId
|
||||
* @param int $fileId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($userId = null, $fileId = null)
|
||||
{
|
||||
if ($user = User::find($userId)) {
|
||||
|
||||
$this->authorize('delete', $user);
|
||||
$rel_path = 'private_uploads/users';
|
||||
|
||||
|
||||
if ($log = Actionlog::find($fileId)) {
|
||||
$filename = $log->filename;
|
||||
$log->delete();
|
||||
|
||||
if (Storage::exists($rel_path.'/'.$filename)) {
|
||||
Storage::delete($rel_path.'/'.$filename);
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/users/message.deletefile.success'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// The log record doesn't exist somehow
|
||||
return redirect()->back()->with('success', trans('admin/users/message.deletefile.success'));
|
||||
}
|
||||
|
||||
return redirect()->route('users.index')->with('error', trans('admin/users/message.user_not_found', ['id' => $userId]));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Display/download the uploaded file
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.6]
|
||||
* @param int $userId
|
||||
* @param int $fileId
|
||||
* @return mixed
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show(User $user, $fileId = null)
|
||||
{
|
||||
|
||||
|
||||
if (empty($fileId)) {
|
||||
return redirect()->route('users.show')->with('error', 'Invalid file request');
|
||||
}
|
||||
|
||||
$this->authorize('view', $user);
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $user->id)->find($fileId)) {
|
||||
$file = 'private_uploads/users/'.$log->filename;
|
||||
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('users.show', ['user' => $user])->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
}
|
||||
|
||||
// The log record doesn't exist somehow
|
||||
return redirect()->route('users.show', ['user' => $user])->with('error', trans('general.log_record_not_found'));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,6 +7,7 @@ use App\Presenters\Presentable;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Model for the Actionlog (the table that keeps a historical log of
|
||||
@@ -462,26 +463,21 @@ class Actionlog extends SnipeModel
|
||||
return route('log.storedeula.download', ['filename' => $this->filename]);
|
||||
}
|
||||
|
||||
switch ($this->item_type) {
|
||||
case Accessory::class:
|
||||
return route('show.accessoryfile', [$this->item_id, $this->id]);
|
||||
case Asset::class:
|
||||
return route('show/assetfile', [$this->item_id, $this->id]);
|
||||
case AssetModel::class:
|
||||
return route('show/modelfile', [$this->item_id, $this->id]);
|
||||
case Consumable::class:
|
||||
return route('show.consumablefile', [$this->item_id, $this->id]);
|
||||
case Component::class:
|
||||
return route('show.componentfile', [$this->item_id, $this->id]);
|
||||
case License::class:
|
||||
return route('show.licensefile', [$this->item_id, $this->id]);
|
||||
case Location::class:
|
||||
return route('show/locationsfile', [$this->item_id, $this->id]);
|
||||
case User::class:
|
||||
return route('show/userfile', [$this->item_id, $this->id]);
|
||||
default:
|
||||
return null;
|
||||
$object = Str::snake(str_plural(str_replace("App\Models\\", '', $this->item_type)));
|
||||
|
||||
if ($object == 'asset_models') {
|
||||
$object = 'models';
|
||||
}
|
||||
|
||||
if ($object == 'asset_maintenances') {
|
||||
$object = 'maintenances';
|
||||
}
|
||||
return route('ui.files.show', [
|
||||
'object_type' => $object,
|
||||
'id' => $this->item_id,
|
||||
'file_id' => $this->id,
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
public function uploads_file_path()
|
||||
@@ -494,6 +490,8 @@ class Actionlog extends SnipeModel
|
||||
switch ($this->item_type) {
|
||||
case Accessory::class:
|
||||
return 'private_uploads/accessories/'.$this->filename;
|
||||
case AssetMaintenance::class:
|
||||
return 'private_uploads/asset_maintenances/'.$this->filename;
|
||||
case Asset::class:
|
||||
return 'private_uploads/assets/'.$this->filename;
|
||||
case AssetModel::class:
|
||||
@@ -514,11 +512,6 @@ class Actionlog extends SnipeModel
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Manually sets $this->source for determineActionSource()
|
||||
public function setActionSource($source = null): void
|
||||
{
|
||||
|
||||
@@ -4,22 +4,25 @@ namespace App\Models;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
use App\Models\Traits\HasUploads;
|
||||
|
||||
/**
|
||||
* Model for Asset Maintenances.
|
||||
*
|
||||
* @version v1.0
|
||||
*/
|
||||
class AssetMaintenance extends Model implements ICompanyableChild
|
||||
class AssetMaintenance extends SnipeModel implements ICompanyableChild
|
||||
{
|
||||
use HasFactory;
|
||||
use HasUploads;
|
||||
use SoftDeletes;
|
||||
use CompanyableChildTrait;
|
||||
use ValidatingTrait;
|
||||
use Loggable, Presentable;
|
||||
|
||||
|
||||
|
||||
@@ -187,6 +190,11 @@ class AssetMaintenance extends Model implements ICompanyableChild
|
||||
->withTrashed();
|
||||
}
|
||||
|
||||
public function getDisplayNameAttribute()
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* -----------------------------------------------
|
||||
* BEGIN QUERY SCOPES
|
||||
|
||||
@@ -14,196 +14,205 @@ use Carbon\Carbon;
|
||||
<div class="row">
|
||||
<div class="col-md-9">
|
||||
|
||||
<div class="box box-default">
|
||||
<div class="box-body">
|
||||
<div class="row-new-striped">
|
||||
<div class="row">
|
||||
<div class="nav-tabs-custom">
|
||||
<ul class="nav nav-tabs hidden-print">
|
||||
|
||||
<div class="col-md-3">
|
||||
{{ trans('admin/asset_maintenances/form.asset_maintenance_type') }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
{{ $assetMaintenance->asset_maintenance_type }}
|
||||
</div>
|
||||
<li class="active">
|
||||
<a href="#info" data-toggle="tab">
|
||||
<span class="hidden-lg hidden-md">
|
||||
<x-icon type="info-circle" class="fa-2x" />
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">{{ trans('admin/users/general.info') }}</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
</div> <!-- /row -->
|
||||
<li>
|
||||
<a href="#files" data-toggle="tab">
|
||||
<span class="hidden-lg hidden-md">
|
||||
<x-icon type="files" class="fa-2x" />
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">{{ trans('general.file_uploads') }}
|
||||
{!! ($assetMaintenance->uploads->count() > 0 ) ? '<span class="badge badge-secondary">'.number_format($assetMaintenance->uploads->count()).'</span>' : '' !!}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
{{ trans('general.asset') }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<a href="{{ route('hardware.show', $assetMaintenance->asset_id) }}">
|
||||
{{ $assetMaintenance->asset->present()->fullName }}
|
||||
</a>
|
||||
</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)
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
{{ trans('general.supplier') }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<a href="{{ route('suppliers.show', $assetMaintenance->supplier_id) }}">
|
||||
{{ $assetMaintenance->supplier->name }}
|
||||
</a>
|
||||
</div>
|
||||
</div> <!-- /row -->
|
||||
@endif
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
{{ trans('admin/asset_maintenances/form.start_date') }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
{{ Helper::getFormattedDateObject($assetMaintenance->start_date, 'date', false) }}
|
||||
</div>
|
||||
</div> <!-- /row -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
{{ trans('admin/asset_maintenances/form.completion_date') }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
@if ($assetMaintenance->completion_date)
|
||||
{{ Helper::getFormattedDateObject($assetMaintenance->completion_date, 'date', false) }}
|
||||
@else
|
||||
{{ trans('admin/asset_maintenances/message.asset_maintenance_incomplete') }}
|
||||
@endif
|
||||
</div>
|
||||
</div> <!-- /row -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
{{ trans('admin/asset_maintenances/form.asset_maintenance_time') }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
{{ $assetMaintenance->asset_maintenance_time }}
|
||||
</div>
|
||||
</div> <!-- /row -->
|
||||
|
||||
@if ($assetMaintenance->cost > 0)
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
{{ trans('admin/asset_maintenances/form.cost') }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
{{ \App\Models\Setting::getSettings()->default_currency .' '. Helper::formatCurrencyOutput($assetMaintenance->cost) }}
|
||||
</div>
|
||||
</div> <!-- /row -->
|
||||
@endif
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
{{ trans('admin/asset_maintenances/form.is_warranty') }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
{{ $assetMaintenance->is_warranty ? trans('admin/asset_maintenances/message.warranty') : trans('admin/asset_maintenances/message.not_warranty') }}
|
||||
</div>
|
||||
</div> <!-- /row -->
|
||||
|
||||
@if ($assetMaintenance->notes)
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
{{ trans('admin/asset_maintenances/form.notes') }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
{!! nl2br(Helper::parseEscapedMarkedownInline($assetMaintenance->notes)) !!}
|
||||
</div>
|
||||
</div> <!-- /row -->
|
||||
@endif
|
||||
|
||||
|
||||
</div><!-- /row-new-striped -->
|
||||
</div><!-- /box-body -->
|
||||
</div><!-- /box -->
|
||||
|
||||
</div> <!-- col-md-9 end -->
|
||||
<div class="col-md-3">
|
||||
|
||||
@if ($assetMaintenance->image!='')
|
||||
<div class="col-md-12 text-center" style="padding-bottom: 17px;">
|
||||
<img src="{{ Storage::disk('public')->url(app('asset_maintenances_path').e($assetMaintenance->image)) }}" class="img-responsive img-thumbnail" style="width:100%" alt="{{ $assetMaintenance->name }}">
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="col-md-12">
|
||||
|
||||
<ul class="list-unstyled" style="line-height: 22px; padding-bottom: 20px;">
|
||||
|
||||
@if ($assetMaintenance->notes)
|
||||
<li>
|
||||
<strong>{{ trans('general.notes') }}</strong>:
|
||||
{!! nl2br(Helper::parseEscapedMarkedownInline($assetMaintenance->notes)) !!}
|
||||
</li>
|
||||
@endif
|
||||
|
||||
@if ($assetMaintenance->address!='')
|
||||
<li>{{ $assetMaintenance->address }}</li>
|
||||
@endif
|
||||
@if ($assetMaintenance->address2!='')
|
||||
<li>{{ $assetMaintenance->address2 }}</li>
|
||||
@endif
|
||||
@if (($assetMaintenance->city!='') || ($assetMaintenance->state!='') || ($assetMaintenance->zip!=''))
|
||||
<li>{{ $assetMaintenance->city }} {{ $assetMaintenance->state }} {{ $assetMaintenance->zip }}</li>
|
||||
@endif
|
||||
@if ($assetMaintenance->manager)
|
||||
<li>{{ trans('admin/users/table.manager') }}: {!! $assetMaintenance->manager->present()->nameUrl() !!}</li>
|
||||
@endif
|
||||
@if ($assetMaintenance->company)
|
||||
<li>{{ trans('admin/companies/table.name') }}: {!! $assetMaintenance->company->present()->nameUrl() !!}</li>
|
||||
@endif
|
||||
@if ($assetMaintenance->parent)
|
||||
<li>{{ trans('admin/locations/table.parent') }}: {!! $assetMaintenance->parent->present()->nameUrl() !!}</li>
|
||||
@endif
|
||||
@if ($assetMaintenance->ldap_ou)
|
||||
<li>{{ trans('admin/locations/table.ldap_ou') }}: {{ $assetMaintenance->ldap_ou }}</li>
|
||||
@endif
|
||||
|
||||
|
||||
@if ((($assetMaintenance->address!='') && ($assetMaintenance->city!='')) || ($assetMaintenance->state!='') || ($assetMaintenance->country!=''))
|
||||
<li>
|
||||
<a href="https://maps.google.com/?q={{ urlencode($assetMaintenance->address.','. $assetMaintenance->city.','.$assetMaintenance->state.','.$assetMaintenance->country.','.$assetMaintenance->zip) }}" target="_blank">
|
||||
{!! trans('admin/locations/message.open_map', ['map_provider_icon' => '<i class="fa-brands fa-google" aria-hidden="true"></i>']) !!}
|
||||
<x-icon type="external-link"/>
|
||||
@can('update', $assetMaintenance)
|
||||
<li class="pull-right">
|
||||
<a href="#" data-toggle="modal" data-target="#uploadFileModal">
|
||||
<span class="hidden-lg hidden-xl hidden-md">
|
||||
<x-icon type="paperclip" class="fa-2x" />
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">
|
||||
<x-icon type="paperclip" />
|
||||
{{ trans('button.upload') }}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://maps.apple.com/?q={{ urlencode($assetMaintenance->address.','. $assetMaintenance->city.','.$assetMaintenance->state.','.$assetMaintenance->country.','.$assetMaintenance->zip) }}" target="_blank">
|
||||
{!! trans('admin/locations/message.open_map', ['map_provider_icon' => '<i class="fa-brands fa-apple" aria-hidden="true" style="font-size: 18px"></i>']) !!}
|
||||
<x-icon type="external-link"/></a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
@endcan
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane active" id="info">
|
||||
<div class="row-new-striped">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-3">
|
||||
{{ trans('admin/asset_maintenances/form.asset_maintenance_type') }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
{{ $assetMaintenance->asset_maintenance_type }}
|
||||
</div>
|
||||
|
||||
</div> <!-- /row -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
{{ trans('general.asset') }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<a href="{{ route('hardware.show', $assetMaintenance->asset_id) }}">
|
||||
{{ $assetMaintenance->asset->present()->fullName }}
|
||||
</a>
|
||||
</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)
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
{{ trans('general.supplier') }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<a href="{{ route('suppliers.show', $assetMaintenance->supplier_id) }}">
|
||||
{{ $assetMaintenance->supplier->name }}
|
||||
</a>
|
||||
</div>
|
||||
</div> <!-- /row -->
|
||||
@endif
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
{{ trans('admin/asset_maintenances/form.start_date') }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
{{ Helper::getFormattedDateObject($assetMaintenance->start_date, 'date', false) }}
|
||||
</div>
|
||||
</div> <!-- /row -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
{{ trans('admin/asset_maintenances/form.completion_date') }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
@if ($assetMaintenance->completion_date)
|
||||
{{ Helper::getFormattedDateObject($assetMaintenance->completion_date, 'date', false) }}
|
||||
@else
|
||||
{{ trans('admin/asset_maintenances/message.asset_maintenance_incomplete') }}
|
||||
@endif
|
||||
</div>
|
||||
</div> <!-- /row -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
{{ trans('admin/asset_maintenances/form.asset_maintenance_time') }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
{{ $assetMaintenance->asset_maintenance_time }}
|
||||
</div>
|
||||
</div> <!-- /row -->
|
||||
|
||||
@if ($assetMaintenance->cost > 0)
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
{{ trans('admin/asset_maintenances/form.cost') }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
{{ \App\Models\Setting::getSettings()->default_currency .' '. Helper::formatCurrencyOutput($assetMaintenance->cost) }}
|
||||
</div>
|
||||
</div> <!-- /row -->
|
||||
@endif
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
{{ trans('admin/asset_maintenances/form.is_warranty') }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
{{ $assetMaintenance->is_warranty ? trans('admin/asset_maintenances/message.warranty') : trans('admin/asset_maintenances/message.not_warranty') }}
|
||||
</div>
|
||||
</div> <!-- /row -->
|
||||
|
||||
@if ($assetMaintenance->notes)
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
{{ trans('admin/asset_maintenances/form.notes') }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
{!! nl2br(Helper::parseEscapedMarkedownInline($assetMaintenance->notes)) !!}
|
||||
</div>
|
||||
</div> <!-- /row -->
|
||||
@endif
|
||||
|
||||
|
||||
</div>
|
||||
</div><!-- /row-new-striped -->
|
||||
<div class="tab-pane" id="files">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<x-filestable object_type="accessories" :object="$assetMaintenance" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /box-body -->
|
||||
</div><!-- /box -->
|
||||
|
||||
</div> <!-- col-md-9 end -->
|
||||
<div class="col-md-3">
|
||||
|
||||
@if ($assetMaintenance->image!='')
|
||||
<div class="col-md-12 text-center" style="padding-bottom: 17px;">
|
||||
<img src="{{ Storage::disk('public')->url(app('asset_maintenances_path').e($assetMaintenance->image)) }}" class="img-responsive img-thumbnail" style="width:100%" alt="{{ $assetMaintenance->name }}">
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="col-md-12">
|
||||
|
||||
<ul class="list-unstyled" style="line-height: 22px; padding-bottom: 20px;">
|
||||
|
||||
@if ($assetMaintenance->notes)
|
||||
<li>
|
||||
<strong>{{ trans('general.notes') }}</strong>:
|
||||
{!! nl2br(Helper::parseEscapedMarkedownInline($assetMaintenance->notes)) !!}
|
||||
</li>
|
||||
@endif
|
||||
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@can('update', $assetMaintenance)
|
||||
@@ -218,4 +227,12 @@ use Carbon\Carbon;
|
||||
|
||||
</div> <!-- row end -->
|
||||
|
||||
@can('assets.files', Asset::class)
|
||||
@include ('modals.upload-file', ['item_type' => 'maintenance', 'item_id' => $assetMaintenance->id])
|
||||
@endcan
|
||||
@stop
|
||||
|
||||
@section('moar_scripts')
|
||||
@include ('partials.bootstrap-table')
|
||||
@stop
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
</div>
|
||||
<form
|
||||
method="POST"
|
||||
action="{{ route('upload/' . $item_type, $item_id) }}"
|
||||
action="{{ route('ui.files.store', ['object_type' => str_plural($item_type), 'id' => $item_id]) }}"
|
||||
accept-charset="UTF-8"
|
||||
class="form-horizontal"
|
||||
enctype="multipart/form-data"
|
||||
|
||||
@@ -1006,7 +1006,7 @@
|
||||
destination = row.item.type;
|
||||
}
|
||||
|
||||
return '<a href="{{ config('app.url') }}/' + destination + '/' + row.item.id + '/showfile/' + row.id + '/delete" '
|
||||
return '<a href="{{ config('app.url') }}/' + destination + '/' + row.item.id + '/files/' + row.id + '/delete" '
|
||||
+ ' data-target="#dataConfirmModal" class="actions btn btn-danger btn-sm delete-asset" data-tooltip="true" '
|
||||
+ ' data-toggle="modal" data-icon="fa-trash"'
|
||||
+ ' data-content="{{ trans('general.file_upload_status.confirm_delete') }}: ' + row.filename + '?" '
|
||||
|
||||
@@ -1314,7 +1314,7 @@ Route::group(['prefix' => 'v1', 'middleware' => ['api', 'api-throttle:api']], fu
|
||||
'index'
|
||||
]
|
||||
)->name('api.files.index')
|
||||
->where(['object_type' => 'assets|hardware|models|users|locations|accessories|consumables|licenses|components']);
|
||||
->where(['object_type' => 'assets|asset_maintenance|hardware|models|users|locations|accessories|consumables|licenses|components']);
|
||||
|
||||
// Get a file
|
||||
Route::get('{object_type}/{id}/files/{file_id}',
|
||||
@@ -1323,7 +1323,7 @@ Route::group(['prefix' => 'v1', 'middleware' => ['api', 'api-throttle:api']], fu
|
||||
'show'
|
||||
]
|
||||
)->name('api.files.show')
|
||||
->where(['object_type' => 'assets|hardware|models|users|locations|accessories|consumables|licenses|components']);
|
||||
->where(['object_type' => 'assets|asset_maintenance|hardware|models|users|locations|accessories|consumables|licenses|components']);
|
||||
|
||||
// Upload files(s)
|
||||
Route::post('{object_type}/{id}/files',
|
||||
@@ -1332,7 +1332,7 @@ Route::group(['prefix' => 'v1', 'middleware' => ['api', 'api-throttle:api']], fu
|
||||
'store'
|
||||
]
|
||||
)->name('api.files.store')
|
||||
->where(['object_type' => 'assets|hardware|models|users|locations|accessories|consumables|licenses|components']);
|
||||
->where(['object_type' => 'assets|asset_maintenance|hardware|models|users|locations|accessories|consumables|licenses|components']);
|
||||
|
||||
// Delete files(s)
|
||||
Route::delete('{object_type}/{id}/files/{file_id}/delete',
|
||||
|
||||
@@ -13,7 +13,7 @@ use App\Http\Controllers\DepreciationsController;
|
||||
use App\Http\Controllers\GroupsController;
|
||||
use App\Http\Controllers\HealthController;
|
||||
use App\Http\Controllers\LabelsController;
|
||||
use App\Http\Controllers\LocationsController;
|
||||
use App\Http\Controllers\UploadedFilesController;
|
||||
use App\Http\Controllers\ManufacturersController;
|
||||
use App\Http\Controllers\ModalController;
|
||||
use App\Http\Controllers\NotesController;
|
||||
@@ -693,6 +693,39 @@ Route::group(['middleware' => 'web'], function () {
|
||||
'logout',
|
||||
[LoginController::class, 'logout']
|
||||
)->name('logout.post');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Uploaded files API routes
|
||||
*/
|
||||
|
||||
// Get a file
|
||||
Route::get('{object_type}/{id}/files/{file_id}',
|
||||
[
|
||||
UploadedFilesController::class,
|
||||
'show'
|
||||
]
|
||||
)->name('ui.files.show')
|
||||
->where(['object_type' => 'assets|maintenances|hardware|models|users|locations|accessories|consumables|licenses|components']);
|
||||
|
||||
// Upload files(s)
|
||||
Route::post('{object_type}/{id}/files',
|
||||
[
|
||||
UploadedFilesController::class,
|
||||
'store'
|
||||
]
|
||||
)->name('ui.files.store')
|
||||
->where(['object_type' => 'assets|maintenances|hardware|models|users|locations|accessories|consumables|licenses|components']);
|
||||
|
||||
// Delete files(s)
|
||||
Route::delete('{object_type}/{id}/files/{file_id}/delete',
|
||||
[
|
||||
UploadedFilesController::class,
|
||||
'destroy'
|
||||
]
|
||||
)->name('ui.files.destroy')
|
||||
->where(['object_type' => 'assets|hardware|models|users|locations|accessories|consumables|licenses|components']);
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -27,21 +27,6 @@ Route::group(['prefix' => 'accessories', 'middleware' => ['auth']], function ()
|
||||
[Accessories\AccessoryCheckinController::class, 'store']
|
||||
)->name('accessories.checkin.store');
|
||||
|
||||
Route::post(
|
||||
'{accessoryId}/upload',
|
||||
[Accessories\AccessoriesFilesController::class, 'store']
|
||||
)->name('upload/accessory');
|
||||
|
||||
Route::delete(
|
||||
'{accessoryId}/deletefile/{fileId}',
|
||||
[Accessories\AccessoriesFilesController::class, 'destroy']
|
||||
)->name('delete/accessoryfile');
|
||||
|
||||
Route::get(
|
||||
'{accessoryId}/showfile/{fileId}/{download?}',
|
||||
[Accessories\AccessoriesFilesController::class, 'show']
|
||||
)->name('show.accessoryfile');
|
||||
|
||||
Route::get('{accessory}/clone',
|
||||
[Accessories\AccessoriesController::class, 'getClone']
|
||||
)->name('clone/accessories');
|
||||
|
||||
@@ -25,20 +25,6 @@ Route::group(['prefix' => 'components', 'middleware' => ['auth']], function () {
|
||||
[Components\ComponentCheckinController::class, 'store']
|
||||
)->name('components.checkin.store');
|
||||
|
||||
Route::post(
|
||||
'{componentId}/upload',
|
||||
[Components\ComponentsFilesController::class, 'store']
|
||||
)->name('upload/component');
|
||||
|
||||
Route::delete(
|
||||
'{componentId}/showfile/{fileId}/delete',
|
||||
[Components\ComponentsFilesController::class, 'destroy']
|
||||
)->name('delete/componentfile');
|
||||
|
||||
Route::get(
|
||||
'{componentId}/showfile/{fileId}/{download?}',
|
||||
[Components\ComponentsFilesController::class, 'show']
|
||||
)->name('show.componentfile');
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -16,20 +16,6 @@ Route::group(['prefix' => 'consumables', 'middleware' => ['auth']], function ()
|
||||
[Consumables\ConsumableCheckoutController::class, 'store']
|
||||
)->name('consumables.checkout.store');
|
||||
|
||||
Route::post(
|
||||
'{consumableId}/upload',
|
||||
[Consumables\ConsumablesFilesController::class, 'store']
|
||||
)->name('upload/consumable');
|
||||
|
||||
Route::delete(
|
||||
'{consumableId}/showfile/{fileId}/delete',
|
||||
[Consumables\ConsumablesFilesController::class, 'destroy']
|
||||
)->name('delete/consumablefile');
|
||||
|
||||
Route::get(
|
||||
'{consumableId}/showfile/{fileId}/{download?}',
|
||||
[Consumables\ConsumablesFilesController::class, 'show']
|
||||
)->name('show.consumablefile');
|
||||
|
||||
Route::get('{consumable}/clone',
|
||||
[Consumables\ConsumablesController::class, 'clone']
|
||||
|
||||
@@ -5,7 +5,6 @@ use App\Http\Controllers\Assets\AssetsController;
|
||||
use App\Http\Controllers\Assets\BulkAssetsController;
|
||||
use App\Http\Controllers\Assets\AssetCheckoutController;
|
||||
use App\Http\Controllers\Assets\AssetCheckinController;
|
||||
use App\Http\Controllers\Assets\AssetFilesController;
|
||||
use App\Models\Setting;
|
||||
use Tabuna\Breadcrumbs\Trail;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
@@ -141,19 +140,6 @@ Route::group(
|
||||
[AssetsController::class, 'getRestore']
|
||||
)->name('restore/hardware')->withTrashed();
|
||||
|
||||
Route::post('{asset}/upload',
|
||||
[AssetFilesController::class, 'store']
|
||||
)->name('upload/asset')->withTrashed();
|
||||
|
||||
Route::get('{asset}/showfile/{fileId}/{download?}',
|
||||
[AssetFilesController::class, 'show']
|
||||
)->name('show/assetfile')->withTrashed();
|
||||
|
||||
Route::delete('{asset}/showfile/{fileId}/delete',
|
||||
[AssetFilesController::class, 'destroy']
|
||||
)->name('delete/assetfile')->withTrashed();
|
||||
Route::get('hardware/bulkedit', [BulkAssetsController::class, 'bulkEditForm'])->name('hardware.bulkedit');
|
||||
|
||||
Route::post(
|
||||
'bulkedit',
|
||||
[BulkAssetsController::class, 'edit']
|
||||
|
||||
@@ -47,19 +47,6 @@ Route::group(['prefix' => 'licenses', 'middleware' => ['auth']], function () {
|
||||
[Licenses\LicenseCheckoutController::class, 'bulkCheckout']
|
||||
)->name('licenses.bulkcheckout');
|
||||
|
||||
Route::post(
|
||||
'{licenseId}/upload',
|
||||
[Licenses\LicenseFilesController::class, 'store']
|
||||
)->name('upload/license');
|
||||
|
||||
Route::delete(
|
||||
'{licenseId}/showfile/{fileId}/delete',
|
||||
[Licenses\LicenseFilesController::class, 'destroy']
|
||||
)->name('delete/licensefile');
|
||||
Route::get(
|
||||
'{licenseId}/showfile/{fileId}/{download?}',
|
||||
[Licenses\LicenseFilesController::class, 'show']
|
||||
)->name('show.licensefile');
|
||||
Route::get(
|
||||
'export',
|
||||
[
|
||||
|
||||
@@ -1,24 +1,10 @@
|
||||
<?php
|
||||
|
||||
use App\Http\Controllers\LocationsController;
|
||||
use App\Http\Controllers\LocationsFilesController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::group(['prefix' => 'locations', 'middleware' => ['auth']], function () {
|
||||
|
||||
Route::post('{location}/upload',
|
||||
[LocationsFilesController::class, 'store']
|
||||
)->name('upload/locations')->withTrashed();
|
||||
|
||||
Route::get('{location}/showfile/{fileId}/{download?}',
|
||||
[LocationsFilesController::class, 'show']
|
||||
)->name('show/locationsfile')->withTrashed();
|
||||
|
||||
Route::delete('{location}/showfile/{fileId}/delete',
|
||||
[LocationsFilesController::class, 'destroy']
|
||||
)->name('delete/locationsfile')->withTrashed();
|
||||
|
||||
|
||||
Route::post(
|
||||
'bulkdelete',
|
||||
[LocationsController::class, 'postBulkDelete']
|
||||
@@ -34,7 +20,6 @@ Route::group(['prefix' => 'locations', 'middleware' => ['auth']], function () {
|
||||
[LocationsController::class, 'postRestore']
|
||||
)->name('locations.restore');
|
||||
|
||||
|
||||
Route::get('{locationId}/clone',
|
||||
[LocationsController::class, 'getClone']
|
||||
)->name('clone/location');
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
|
||||
use App\Http\Controllers\AssetModelsController;
|
||||
use App\Http\Controllers\AssetModelsFilesController;
|
||||
use App\Http\Controllers\BulkAssetModelsController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Tabuna\Breadcrumbs\Trail;
|
||||
@@ -11,18 +10,6 @@ use Tabuna\Breadcrumbs\Trail;
|
||||
|
||||
Route::group(['prefix' => 'models', 'middleware' => ['auth']], function () {
|
||||
|
||||
Route::post('{model}/upload',
|
||||
[AssetModelsFilesController::class, 'store']
|
||||
)->name('upload/models')->withTrashed();
|
||||
|
||||
Route::get('{model}/showfile/{fileId}/{download?}',
|
||||
[AssetModelsFilesController::class, 'show']
|
||||
)->name('show/modelfile')->withTrashed();
|
||||
|
||||
Route::delete('{model}/showfile/{fileId}/delete',
|
||||
[AssetModelsFilesController::class, 'destroy']
|
||||
)->name('delete/modelfile')->withTrashed();
|
||||
|
||||
Route::get(
|
||||
'{model}/clone',
|
||||
[
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
|
||||
use App\Http\Controllers\Users;
|
||||
use App\Http\Controllers\Users\UserFilesController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
// User Management
|
||||
@@ -64,30 +63,6 @@ Route::group(['prefix' => 'users', 'middleware' => ['auth']], function () {
|
||||
]
|
||||
)->name('unsuspend/user');
|
||||
|
||||
Route::post(
|
||||
'{user}/upload',
|
||||
[
|
||||
Users\UserFilesController::class,
|
||||
'store'
|
||||
]
|
||||
)->name('upload/user')->withTrashed();
|
||||
|
||||
Route::delete(
|
||||
'{userId}/showfile/{fileId}/delete',
|
||||
[
|
||||
Users\UserFilesController::class,
|
||||
'destroy'
|
||||
]
|
||||
)->name('userfile.destroy');
|
||||
|
||||
Route::get(
|
||||
'{user}/showfile/{fileId}',
|
||||
[
|
||||
Users\UserFilesController::class,
|
||||
'show'
|
||||
]
|
||||
)->name('show/userfile')->withTrashed();
|
||||
|
||||
Route::post(
|
||||
'{userId}/password',
|
||||
[
|
||||
|
||||
2
storage/private_uploads/asset_maintenances/.gitignore
vendored
Executable file
2
storage/private_uploads/asset_maintenances/.gitignore
vendored
Executable file
@@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
||||
@@ -47,7 +47,6 @@ class CreateAssetMaintenanceTest extends TestCase
|
||||
->assertOk()
|
||||
->assertStatus(200);
|
||||
|
||||
\Log::error($response->json());
|
||||
// Since we rename the file in the ImageUploadRequest, we have to fetch the record from the database
|
||||
$assetMaintenance = AssetMaintenance::where('title', 'Test Maintenance')->first();
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ class UpdateLocationsTest extends TestCase
|
||||
$file = UploadedFile::fake()->image('file.jpg', 100, 100)->size(100);
|
||||
|
||||
$this->actingAs(User::factory()->superuser()->create())
|
||||
->post(route('upload/locations', $location), [
|
||||
->post(route('ui.files.store', ['object_type' => 'locations', 'id' => $location->id]), [
|
||||
'file' => [$file],
|
||||
'notes' => 'Test Upload',
|
||||
])
|
||||
|
||||
Reference in New Issue
Block a user