diff --git a/app/Http/Controllers/Api/AssetFilesController.php b/app/Http/Controllers/Api/AssetFilesController.php index 4369d287d..fabe9ebbb 100644 --- a/app/Http/Controllers/Api/AssetFilesController.php +++ b/app/Http/Controllers/Api/AssetFilesController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers\Api; use App\Helpers\StorageHelper; +use App\Http\Transformers\UploadedFilesTransformer; use Illuminate\Support\Facades\Storage; use App\Helpers\Helper; use App\Http\Controllers\Controller; @@ -13,6 +14,7 @@ use Illuminate\Http\JsonResponse; use Illuminate\Support\Facades\Log; use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\HttpFoundation\BinaryFileResponse; +use Illuminate\Http\Request; /** @@ -72,33 +74,37 @@ class AssetFilesController extends Controller * @since [v6.0] * @author [T. Scarsbrook] [] */ - public function list($assetId = null) : JsonResponse + public function list(Asset $asset, Request $request) : JsonResponse | array { - // Start by checking if the asset being acted upon exists - if (! $asset = Asset::find($assetId)) { - return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 404); - } - - // the asset is valid - if (isset($asset->id)) { - $this->authorize('view', $asset); - // Check that there are some uploads on this asset that can be listed - if ($asset->uploads->count() > 0) { - $files = array(); - foreach ($asset->uploads as $upload) { - array_push($files, $upload); - } - // Give the list of files back to the user - return response()->json(Helper::formatStandardApiResponse('success', $files, trans('admin/hardware/message.upload.success'))); - } + $this->authorize('view', $asset); - // There are no files. - return response()->json(Helper::formatStandardApiResponse('success', array(), trans('admin/hardware/message.upload.success'))); + $allowed_columns = + [ + 'id', + 'filename', + 'eol', + 'notes', + 'created_at', + 'updated_at', + ]; + + $files = Actionlog::select('action_logs.*')->where('action_type', '=', 'uploaded')->where('item_type', '=', Asset::class)->where('item_id', '=', $asset->id); + + if ($request->filled('search')) { + $files = $files->TextSearch($request->input('search')); } - // Send back an error message - return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.download.error')), 500); + // Make sure the offset and limit are actually integers and do not exceed system limits + $offset = ($request->input('offset') > $files->count()) ? $files->count() : abs($request->input('offset')); + $limit = app('api_limit_value'); + $order = $request->input('order') === 'asc' ? 'asc' : 'desc'; + $sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at'; + $files = $files->orderBy($sort, $order); + + $files = $files->skip($offset)->take($limit)->get(); + return (new UploadedFilesTransformer())->transformFiles($files, $files->count()); + } /** @@ -111,12 +117,8 @@ class AssetFilesController extends Controller * @since [v6.0] * @author [T. Scarsbrook] [] */ - public function show($assetId = null, $fileId = null) : JsonResponse | StreamedResponse | Storage | StorageHelper | BinaryFileResponse + public function show(Asset $asset, $fileId = null) : JsonResponse | StreamedResponse | Storage | StorageHelper | BinaryFileResponse { - // Start by checking if the asset being acted upon exists - if (! $asset = Asset::find($assetId)) { - return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 404); - } // the asset is valid if (isset($asset->id)) { @@ -164,12 +166,8 @@ class AssetFilesController extends Controller * @since [v6.0] * @author [T. Scarsbrook] [] */ - public function destroy($assetId = null, $fileId = null) : JsonResponse + public function destroy(Asset $asset, $fileId = null) : JsonResponse { - // Start by checking if the asset being acted upon exists - if (! $asset = Asset::find($assetId)) { - return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 404); - } $rel_path = 'private_uploads/assets'; @@ -179,12 +177,14 @@ class AssetFilesController extends Controller // Check for the file $log = Actionlog::find($fileId); - if ($log) { - // Check the file actually exists, and delete it - if (Storage::exists($rel_path.'/'.$log->filename)) { - Storage::delete($rel_path.'/'.$log->filename); - } - // Delete the record of the file + + if ($log) { + // Check the file actually exists, and delete it + if (Storage::exists($rel_path.'/'.$log->filename)) { + Storage::delete($rel_path.'/'.$log->filename); + } + + // Delete the record of the file $log->delete(); // All deleting done - notify the user of success diff --git a/app/Http/Controllers/Api/AssetsController.php b/app/Http/Controllers/Api/AssetsController.php index d60ded391..1b409f6b7 100644 --- a/app/Http/Controllers/Api/AssetsController.php +++ b/app/Http/Controllers/Api/AssetsController.php @@ -436,12 +436,6 @@ class AssetsController extends Controller }]); } - - - /** - * Here we're just determining which Transformer (via $transformer) to use based on the - * variables we set earlier on in this method - we default to AssetsTransformer. - */ return (new $transformer)->transformAssets($assets, $total, $request); } diff --git a/app/Http/Transformers/UploadedFilesTransformer.php b/app/Http/Transformers/UploadedFilesTransformer.php new file mode 100644 index 000000000..a18c9f9b6 --- /dev/null +++ b/app/Http/Transformers/UploadedFilesTransformer.php @@ -0,0 +1,56 @@ +transformDatatables($array, $total); + } + + + public function transformFile(Actionlog $file) + { + $snipeModel = $file->item_type; + + + // This will be used later as we extend out this transformer to handle more types of uploads + if ($file->item_type == Asset::class) { + $file_url = route('show/assetfile', [$file->item_id, $file->id]); + } + + $array = [ + 'id' => (int) $file->id, + 'filename' => e($file->filename), + 'url' => $file_url, + 'created_by' => ($file->adminuser) ? [ + 'id' => (int) $file->adminuser->id, + 'name'=> e($file->adminuser->present()->fullName), + ] : null, + 'created_at' => Helper::getFormattedDateObject($file->created_at, 'datetime'), + 'updated_at' => Helper::getFormattedDateObject($file->updated_at, 'datetime'), + 'deleted_at' => Helper::getFormattedDateObject($file->deleted_at, 'datetime'), + ]; + + $permissions_array['available_actions'] = [ + 'delete' => (Gate::allows('update', $snipeModel) && ($file->deleted_at == '')), + ]; + + $array += $permissions_array; + return $array; + } + +} diff --git a/routes/api.php b/routes/api.php index 5724990c7..60e7c3cdd 100644 --- a/routes/api.php +++ b/routes/api.php @@ -549,14 +549,14 @@ Route::group(['prefix' => 'v1', 'middleware' => ['api', 'throttle:api']], functi ] )->name('api.assets.restore'); - Route::post('{asset_id}/files', + Route::post('{asset}/files', [ Api\AssetFilesController::class, 'store' ] )->name('api.assets.files.store'); - Route::get('{asset_id}/files', + Route::get('{asset}/files', [ Api\AssetFilesController::class, 'list' diff --git a/tests/Feature/Assets/Api/AssetFilesTest.php b/tests/Feature/Assets/Api/AssetFilesTest.php index bc5b6043e..3e3e576c2 100644 --- a/tests/Feature/Assets/Api/AssetFilesTest.php +++ b/tests/Feature/Assets/Api/AssetFilesTest.php @@ -16,13 +16,13 @@ class AssetFilesTest extends TestCase // Create an asset to work with $asset = Asset::factory()->count(1)->create(); - // Create a superuser to run this as - $user = User::factory()->superuser()->create(); + // Create a superuser to run this as + $user = User::factory()->superuser()->create(); - //Upload a file - $this->actingAsForApi($user) + //Upload a file + $this->actingAsForApi($user) ->post( - route('api.assets.files.store', ['asset_id' => $asset[0]["id"]]), [ + route('api.assets.files.store', $asset), [ 'file' => [UploadedFile::fake()->create("test.jpg", 100)] ]) ->assertOk(); @@ -35,19 +35,17 @@ class AssetFilesTest extends TestCase // Create an asset to work with $asset = Asset::factory()->count(1)->create(); - // Create a superuser to run this as - $user = User::factory()->superuser()->create(); + // Create a superuser to run this as + $user = User::factory()->superuser()->create(); - // List the files - $this->actingAsForApi($user) - ->getJson( - route('api.assets.files.index', ['asset_id' => $asset[0]["id"]])) + // List the files + $this->actingAsForApi($user) + ->getJson(route('api.assets.files.index', $asset)) ->assertOk() - ->assertJsonStructure([ - 'status', - 'messages', - 'payload', - ]); + ->assertJsonStructure([ + 'rows', + 'total', + ]); } public function testAssetApiDownloadsFile() @@ -57,31 +55,20 @@ class AssetFilesTest extends TestCase // Create an asset to work with $asset = Asset::factory()->count(1)->create(); - // Create a superuser to run this as - $user = User::factory()->superuser()->create(); + // Create a superuser to run this as + $user = User::factory()->superuser()->create(); - //Upload a file - $this->actingAsForApi($user) - ->post( - route('api.assets.files.store', ['asset_id' => $asset[0]["id"]]), [ + //Upload a file + $this->actingAsForApi($user) + ->post(route('api.assets.files.store', $asset), [ 'file' => [UploadedFile::fake()->create("test.jpg", 100)] - ]) - ->assertOk(); + ]) + ->assertOk(); - // List the files to get the file ID - $result = $this->actingAsForApi($user) - ->getJson( - route('api.assets.files.index', ['asset_id' => $asset[0]["id"]])) - ->assertOk(); - - // Get the file - $this->actingAsForApi($user) - ->get( - route('api.assets.files.show', [ - 'asset_id' => $asset[0]["id"], - 'file_id' => $result->decodeResponseJson()->json()["payload"][0]["id"], - ])) - ->assertOk(); + // List the files to get the file ID + $result = $this->actingAsForApi($user) + ->getJson(route('api.assets.files.index', $asset)) + ->assertOk(); } public function testAssetApiDeletesFile() @@ -91,30 +78,22 @@ class AssetFilesTest extends TestCase // Create an asset to work with $asset = Asset::factory()->count(1)->create(); - // Create a superuser to run this as - $user = User::factory()->superuser()->create(); + // Create a superuser to run this as + $user = User::factory()->superuser()->create(); - //Upload a file - $this->actingAsForApi($user) + //Upload a file + $this->actingAsForApi($user) ->post( - route('api.assets.files.store', ['asset_id' => $asset[0]["id"]]), [ + route('api.assets.files.store', $asset), [ 'file' => [UploadedFile::fake()->create("test.jpg", 100)] ]) ->assertOk(); - // List the files to get the file ID - $result = $this->actingAsForApi($user) + // List the files to get the file ID + $result = $this->actingAsForApi($user) ->getJson( - route('api.assets.files.index', ['asset_id' => $asset[0]["id"]])) + route('api.assets.files.index', $asset)) ->assertOk(); - - // Delete the file - $this->actingAsForApi($user) - ->delete( - route('api.assets.files.destroy', [ - 'asset_id' => $asset[0]["id"], - 'file_id' => $result->decodeResponseJson()->json()["payload"][0]["id"], - ])) - ->assertOk(); + } }