mirror of
https://github.com/snipe/snipe-it.git
synced 2026-02-04 21:35:34 +00:00
Added uploaded files API controllers and presenters
Signed-off-by: snipe <snipe@snipe.net>
This commit is contained in:
@ -116,9 +116,17 @@ class Handler extends ExceptionHandler
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Method not allowed'), 405);
|
||||
default:
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $statusCode), $statusCode);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// This handles API validation exceptions that happen at the Form Request level, so they
|
||||
// never even get to the controller where we normally nicely format JSON responses
|
||||
if ($e instanceof ValidationException) {
|
||||
$response = $this->invalidJson($request, $e);
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $e->errors()), 200);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -48,6 +48,7 @@ class StorageHelper
|
||||
'avif',
|
||||
'webp',
|
||||
'png',
|
||||
'gif',
|
||||
];
|
||||
|
||||
|
||||
@ -59,6 +60,18 @@ class StorageHelper
|
||||
|
||||
}
|
||||
|
||||
public static function getFiletype($file_with_path) {
|
||||
|
||||
// The file exists and is allowed to be displayed inline
|
||||
if (Storage::exists($file_with_path)) {
|
||||
return pathinfo($file_with_path, PATHINFO_EXTENSION);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decide whether to show the file inline or download it.
|
||||
*/
|
||||
|
||||
244
app/Http/Controllers/Api/UploadedFilesController.php
Normal file
244
app/Http/Controllers/Api/UploadedFilesController.php
Normal file
@ -0,0 +1,244 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Http\Transformers\UploadedFilesTransformer;
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
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\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
||||
|
||||
class UploadedFilesController extends Controller
|
||||
{
|
||||
|
||||
|
||||
static $map_object_type = [
|
||||
'accessories' => Accessory::class,
|
||||
'assets' => Asset::class,
|
||||
'components' => Component::class,
|
||||
'consumables' => Consumable::class,
|
||||
'licenses' => License::class,
|
||||
'locations' => Location::class,
|
||||
'models' => AssetModel::class,
|
||||
'users' => User::class,
|
||||
];
|
||||
|
||||
static $map_storage_path = [
|
||||
'accessories' => 'private_uploads/accessories/',
|
||||
'assets' => 'private_uploads/assets/',
|
||||
'components' => 'private_uploads/components/',
|
||||
'consumables' => 'private_uploads/consumables/',
|
||||
'licenses' => 'private_uploads/licenses/',
|
||||
'locations' => 'private_uploads/locations/',
|
||||
'models' => 'private_uploads/assetmodels/',
|
||||
'users' => 'private_uploads/users/',
|
||||
];
|
||||
|
||||
static $map_file_prefix= [
|
||||
'accessories' => 'accessory',
|
||||
'assets' => 'asset',
|
||||
'components' => 'component',
|
||||
'consumables' => 'consumable',
|
||||
'licenses' => 'license',
|
||||
'locations' => 'location',
|
||||
'models' => 'model',
|
||||
'users' => 'user',
|
||||
];
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* List the files for an object.
|
||||
*
|
||||
* @since [v7.0.12]
|
||||
* @author [r-xyz]
|
||||
*/
|
||||
public function index(Request $request, $object_type, $id) : JsonResponse | array
|
||||
{
|
||||
|
||||
$object = self::$map_object_type[$object_type]::find($id);
|
||||
$this->authorize('view', $object);
|
||||
|
||||
if (!$object) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.file_upload_status.invalid_object')));
|
||||
}
|
||||
|
||||
// Columns allowed for sorting
|
||||
$allowed_columns =
|
||||
[
|
||||
'id',
|
||||
'filename',
|
||||
'action_type',
|
||||
'note',
|
||||
'created_at',
|
||||
];
|
||||
|
||||
$uploads = $object->uploads();
|
||||
$offset = ($request->input('offset') > $object->count()) ? $object->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') : 'action_logs.created_at';
|
||||
|
||||
// Text search on action_logs fields
|
||||
// We could use the normal Actionlogs text scope, but it's a very heavy query since it's searcghing across all relations
|
||||
// And we generally won't need that here
|
||||
if ($request->filled('search')) {
|
||||
|
||||
$uploads->where(function ($query) use ($request) {
|
||||
$query->where('filename', 'LIKE', '%' . $request->input('search') . '%')
|
||||
->orWhere('note', 'LIKE', '%' . $request->input('search') . '%');
|
||||
});
|
||||
}
|
||||
|
||||
$uploads = $uploads->skip($offset)->take($limit)->orderBy($sort, $order)->get();
|
||||
return (new UploadedFilesTransformer())->transformFiles($uploads, $uploads->count());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Accepts a POST to upload a file to the server.
|
||||
*
|
||||
* @param \App\Http\Requests\UploadFileRequest $request
|
||||
* @param int $assetModelId
|
||||
* @since [v7.0.12]
|
||||
* @author [r-xyz]
|
||||
*/
|
||||
public function store(UploadFileRequest $request, $object_type, $id) : JsonResponse
|
||||
{
|
||||
|
||||
$object = self::$map_object_type[$object_type]::find($id);
|
||||
$this->authorize('view', $object);
|
||||
|
||||
if (!$object) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 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 response()->json(Helper::formatStandardApiResponse('success', (new UploadedFilesTransformer())->transformFiles($files, count($files)), trans_choice('general.file_upload_status.upload.success', count($files))));
|
||||
}
|
||||
|
||||
// No files were submitted
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.file_upload_status.nofiles')));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Check for permissions and display the file.
|
||||
*
|
||||
* @param AssetModel $model
|
||||
* @param int $fileId
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @since [v7.0.12]
|
||||
* @author [r-xyz]
|
||||
*/
|
||||
public function show($object_type, $id, $file_id) : JsonResponse | StreamedResponse | Storage | StorageHelper | BinaryFileResponse
|
||||
{
|
||||
$object = self::$map_object_type[$object_type]::find($id);
|
||||
$this->authorize('view', $object);
|
||||
|
||||
if (!$object) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.file_upload_status.invalid_object')));
|
||||
}
|
||||
|
||||
|
||||
// Check that the file being requested exists for the asset
|
||||
if (! $log = Actionlog::whereNotNull('filename')
|
||||
->where('item_type', AssetModel::class)
|
||||
->where('item_id', $object->id)->find($file_id)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.file_upload_status.invalid_id')), 200);
|
||||
}
|
||||
|
||||
|
||||
if (! Storage::exists(self::$map_storage_path[$object_type].'/'.$log->filename)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.file_upload_status.file_not_found'), 200));
|
||||
}
|
||||
|
||||
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 AssetModel $model
|
||||
* @param int $fileId
|
||||
* @since [v7.0.12]
|
||||
* @author [r-xyz]
|
||||
*/
|
||||
public function destroy($object_type, $id, $file_id) : JsonResponse
|
||||
{
|
||||
|
||||
$object = self::$map_object_type[$object_type]::find($id);
|
||||
$this->authorize('update', self::$map_object_type[$object_type]);
|
||||
|
||||
if (!$object) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 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 response()->json(Helper::formatStandardApiResponse('success', null, trans_choice('general.file_upload_status.delete.success', 1)), 200);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// The file doesn't seem to really exist, so report an error
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans_choice('general.file_upload_status.delete.error', 1)), 500);
|
||||
|
||||
}
|
||||
}
|
||||
@ -6,6 +6,7 @@ use App\Http\Traits\ConvertsBase64ToFiles;
|
||||
use enshrined\svgSanitize\Sanitizer;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use \App\Helpers\Helper;
|
||||
|
||||
class UploadFileRequest extends Request
|
||||
{
|
||||
@ -27,44 +28,62 @@ class UploadFileRequest extends Request
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
$max_file_size = \App\Helpers\Helper::file_upload_max_size();
|
||||
$max_file_size = Helper::file_upload_max_size();
|
||||
|
||||
return [
|
||||
'file.*' => 'required|mimes:png,gif,jpg,svg,jpeg,doc,docx,pdf,txt,zip,rar,xls,xlsx,lic,xml,rtf,json,webp,avif|max:'.$max_file_size,
|
||||
'file.*' => 'required|mimes:png,gif,jpg,svg,jpeg,doc,docx,pdf,txt,zip,rar,xls,xlsx,lic,xml,rtf,json,webp,avif|max:'.$max_file_size,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes (if needed) and Saves a file to the appropriate location
|
||||
* Returns the 'short' (storage-relative) filename
|
||||
*
|
||||
* TODO - this has a lot of similarities to UploadImageRequest's handleImage; is there
|
||||
* a way to merge them or extend one into the other?
|
||||
*/
|
||||
public function handleFile(string $dirname, string $name_prefix, $file): string
|
||||
{
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$file_name = $name_prefix.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$file->guessExtension();
|
||||
|
||||
$file_name = $name_prefix.'-'.str_random(8).'-'.str_replace(' ', '-', $file->getClientOriginalName());
|
||||
|
||||
// Check for SVG and sanitize it
|
||||
if ($file->getMimeType() === 'image/svg+xml') {
|
||||
Log::debug('This is an SVG');
|
||||
Log::debug($file_name);
|
||||
|
||||
$sanitizer = new Sanitizer();
|
||||
$dirtySVG = file_get_contents($file->getRealPath());
|
||||
$cleanSVG = $sanitizer->sanitize($dirtySVG);
|
||||
|
||||
try {
|
||||
Storage::put($dirname.$file_name, $cleanSVG);
|
||||
} catch (\Exception $e) {
|
||||
Log::debug('Upload no workie :( ');
|
||||
Log::debug($e);
|
||||
}
|
||||
|
||||
$uploaded_file = $this->handleSVG($file);
|
||||
} else {
|
||||
$put_results = Storage::put($dirname.$file_name, file_get_contents($file));
|
||||
$uploaded_file = file_get_contents($file);
|
||||
}
|
||||
|
||||
try {
|
||||
Storage::put($dirname.$file_name, $uploaded_file);
|
||||
} catch (\Exception $e) {
|
||||
Log::debug($e);
|
||||
}
|
||||
|
||||
return $file_name;
|
||||
}
|
||||
}
|
||||
|
||||
public function handleSVG($file) {
|
||||
$sanitizer = new Sanitizer();
|
||||
$dirtySVG = file_get_contents($file->getRealPath());
|
||||
return $sanitizer->sanitize($dirtySVG);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the validation error messages that apply to the request, but
|
||||
* replace the attribute name with the name of the file that was attempted and failed
|
||||
* to make it clearer to the user which file is the bad one.
|
||||
* @return array
|
||||
*/
|
||||
public function attributes(): array
|
||||
{
|
||||
$attributes = [];
|
||||
|
||||
if ($this->file) {
|
||||
for ($i = 0; $i < count($this->file); $i++) {
|
||||
$attributes['file.'.$i] = $this->file[$i]->getClientOriginalName();
|
||||
}
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
|
||||
}
|
||||
}
|
||||
@ -4,6 +4,10 @@ namespace App\Http\Transformers;
|
||||
|
||||
class DatatablesTransformer
|
||||
{
|
||||
|
||||
/**
|
||||
* Transform data for bootstrap tables and API responses for lists of things
|
||||
**/
|
||||
public function transformDatatables($objects, $total = null)
|
||||
{
|
||||
(isset($total)) ? $objects_array['total'] = $total : $objects_array['total'] = count($objects);
|
||||
@ -11,4 +15,15 @@ class DatatablesTransformer
|
||||
|
||||
return $objects_array;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform data for returning the status of items within a bulk action
|
||||
**/
|
||||
public function transformBulkResponseWithStatusAndObjects($objects, $total)
|
||||
{
|
||||
(isset($total)) ? $objects_array['total'] = $total : $objects_array['total'] = count($objects);
|
||||
$objects_array['rows'] = $objects;
|
||||
|
||||
return $objects_array;
|
||||
}
|
||||
}
|
||||
@ -3,10 +3,10 @@
|
||||
namespace App\Http\Transformers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class UploadedFilesTransformer
|
||||
@ -26,23 +26,26 @@ class UploadedFilesTransformer
|
||||
{
|
||||
$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,
|
||||
'icon' => Helper::filetype_icon($file->filename),
|
||||
'name' => e($file->filename),
|
||||
'item' => ($file->item_type) ? [
|
||||
'id' => (int) $file->item_id,
|
||||
'type' => strtolower(class_basename($file->item_type)),
|
||||
] : null,
|
||||
'filename' => e($file->filename),
|
||||
'url' => $file_url,
|
||||
'filetype' => StorageHelper::getFiletype($file->uploads_file_path()),
|
||||
'url' => $file->uploads_file_url(),
|
||||
'note' => ($file->note) ? e($file->note) : null,
|
||||
'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'),
|
||||
'inline' => StorageHelper::allowSafeInline($file->uploads_file_path()),
|
||||
'exists_on_disk' => (Storage::exists($file->uploads_file_path()) ? true : false),
|
||||
];
|
||||
|
||||
$permissions_array['available_actions'] = [
|
||||
@ -53,4 +56,5 @@ class UploadedFilesTransformer
|
||||
return $array;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -69,8 +69,8 @@ class Actionlog extends SnipeModel
|
||||
*/
|
||||
protected $searchableRelations = [
|
||||
'company' => ['name'],
|
||||
'adminuser' => ['first_name','last_name','username', 'email', 'employee_num'],
|
||||
'user' => ['first_name','last_name','username', 'email', 'employee_num'],
|
||||
'adminuser' => ['first_name','last_name','username', 'email'],
|
||||
'user' => ['first_name','last_name','username', 'email'],
|
||||
'assets' => ['asset_tag','name', 'serial', 'order_number', 'notes', 'purchase_date'],
|
||||
'assets.model' => ['name', 'model_number', 'eol', 'notes'],
|
||||
'assets.model.category' => ['name', 'notes'],
|
||||
@ -113,13 +113,7 @@ class Actionlog extends SnipeModel
|
||||
} elseif (auth()->user() && auth()->user()->company) {
|
||||
$actionlog->company_id = auth()->user()->company_id;
|
||||
}
|
||||
|
||||
if ($actionlog->action_date == '') {
|
||||
$actionlog->action_date = Carbon::now();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -251,8 +245,8 @@ class Actionlog extends SnipeModel
|
||||
public function uploads()
|
||||
{
|
||||
return $this->morphTo('item')
|
||||
->where('action_type', '=', 'uploaded')
|
||||
->withTrashed();
|
||||
->where('action_type', '=', 'uploaded')
|
||||
->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -277,7 +271,7 @@ class Actionlog extends SnipeModel
|
||||
public function adminuser()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'created_by')
|
||||
->withTrashed();
|
||||
->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -382,7 +376,7 @@ class Actionlog extends SnipeModel
|
||||
if ($this->created_at > $override_default_next) {
|
||||
$next_audit_days = '-'.$next_audit_days;
|
||||
}
|
||||
|
||||
|
||||
return $next_audit_days;
|
||||
}
|
||||
|
||||
@ -414,10 +408,10 @@ class Actionlog extends SnipeModel
|
||||
public function getListingOfActionLogsChronologicalOrder()
|
||||
{
|
||||
return $this->all()
|
||||
->where('action_type', '!=', 'uploaded')
|
||||
->orderBy('item_id', 'asc')
|
||||
->orderBy('created_at', 'asc')
|
||||
->get();
|
||||
->where('action_type', '!=', 'uploaded')
|
||||
->orderBy('item_id', 'asc')
|
||||
->orderBy('created_at', 'asc')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -440,7 +434,7 @@ class Actionlog extends SnipeModel
|
||||
return 'api';
|
||||
}
|
||||
|
||||
// This is probably NOT an API call
|
||||
// This is probably NOT an API call
|
||||
if (request()->filled('_token')) {
|
||||
return 'gui';
|
||||
}
|
||||
@ -450,6 +444,62 @@ class Actionlog extends SnipeModel
|
||||
|
||||
}
|
||||
|
||||
public function uploads_file_url()
|
||||
{
|
||||
|
||||
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/locationsfile', [$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;
|
||||
}
|
||||
}
|
||||
|
||||
public function uploads_file_path()
|
||||
{
|
||||
|
||||
switch ($this->item_type) {
|
||||
case Accessory::class:
|
||||
return 'private_uploads/accessories/'.$this->filename;
|
||||
case Asset::class:
|
||||
return 'private_uploads/assets/'.$this->filename;
|
||||
case AssetModel::class:
|
||||
return 'private_uploads/assetmodels/'.$this->filename;
|
||||
case Consumable::class:
|
||||
return 'private_uploads/consumables/'.$this->filename;
|
||||
case Component::class:
|
||||
return 'private_uploads/components/'.$this->filename;
|
||||
case License::class:
|
||||
return 'private_uploads/licenses/'.$this->filename;
|
||||
case Location::class:
|
||||
return 'private_uploads/locations/'.$this->filename;
|
||||
case User::class:
|
||||
return 'private_uploads/users/'.$this->filename;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Manually sets $this->source for determineActionSource()
|
||||
public function setActionSource($source = null): void
|
||||
{
|
||||
@ -460,4 +510,4 @@ class Actionlog extends SnipeModel
|
||||
{
|
||||
return $query->leftJoin('users as admin_sort', 'action_logs.created_by', '=', 'admin_sort.id')->select('action_logs.*')->orderBy('admin_sort.first_name', $order)->orderBy('admin_sort.last_name', $order);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -29,7 +29,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
use CompanyableTrait;
|
||||
|
||||
protected $presenter = \App\Presenters\UserPresenter::class;
|
||||
use SoftDeletes, ValidatingTrait;
|
||||
use SoftDeletes, ValidatingTrait, Loggable;
|
||||
use Authenticatable, Authorizable, CanResetPassword, HasApiTokens;
|
||||
use UniqueUndeletedTrait;
|
||||
use Notifiable;
|
||||
|
||||
101
app/Presenters/UploadedFilesPresenter.php
Normal file
101
app/Presenters/UploadedFilesPresenter.php
Normal file
@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace App\Presenters;
|
||||
|
||||
/**
|
||||
* Class AccessoryPresenter
|
||||
*/
|
||||
class UploadsPresenter extends Presenter
|
||||
{
|
||||
/**
|
||||
* Json Column Layout for bootstrap table
|
||||
* @return string
|
||||
*/
|
||||
public static function dataTableLayout($object)
|
||||
{
|
||||
|
||||
if ($object =='assets') {
|
||||
$object = 'hardware';
|
||||
}
|
||||
|
||||
$layout = [
|
||||
[
|
||||
'field' => 'id',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('general.id'),
|
||||
'visible' => false,
|
||||
],
|
||||
[
|
||||
'field' => 'icon',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'switchable' => false,
|
||||
'title' => trans('general.type'),
|
||||
'formatter' => 'iconFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'image',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'switchable' => true,
|
||||
'title' => trans('general.image'),
|
||||
'formatter' => 'inlineImageFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'filename',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'switchable' => true,
|
||||
'title' => trans('general.file_name'),
|
||||
'visible' => true,
|
||||
'formatter' => 'fileUploadNameFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'download',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'switchable' => true,
|
||||
'title' => trans('general.download'),
|
||||
'visible' => true,
|
||||
'formatter' => 'downloadOrOpenInNewWindowFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'note',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('general.notes'),
|
||||
'visible' => true,
|
||||
],
|
||||
[
|
||||
'field' => 'created_by',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'title' => trans('general.created_by'),
|
||||
'visible' => false,
|
||||
'formatter' => 'usersLinkObjFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'created_at',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('general.created_at'),
|
||||
'visible' => false,
|
||||
'formatter' => 'dateDisplayFormatter',
|
||||
], [
|
||||
'field' => 'available_actions',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'switchable' => false,
|
||||
'title' => trans('table.actions'),
|
||||
'formatter' => 'deleteUploadFormatter',
|
||||
],
|
||||
];
|
||||
|
||||
return json_encode($layout);
|
||||
}
|
||||
|
||||
}
|
||||
@ -640,4 +640,24 @@ return [
|
||||
],
|
||||
],
|
||||
|
||||
'file_upload_status' => [
|
||||
|
||||
'upload' => [
|
||||
'success' => 'File successfully uploaded |:count files successfully uploaded',
|
||||
'error' => 'File upload failed |:count file uploads failed',
|
||||
],
|
||||
|
||||
'delete' => [
|
||||
'success' => 'File successfully deleted |:count files successfully deleted',
|
||||
'error' => 'File deletion failed |:count file deletions failed',
|
||||
],
|
||||
|
||||
'file_not_found' => 'The selected file was not found on server',
|
||||
'invalid_id' => 'That file ID is invalid',
|
||||
'invalid_object' => 'That object ID is invalid',
|
||||
'nofiles' => 'No files were included for upload',
|
||||
'confirm_delete' => 'Are you sure you want to delete this file?',
|
||||
],
|
||||
|
||||
|
||||
];
|
||||
|
||||
101
routes/api.php
101
routes/api.php
@ -556,35 +556,6 @@ Route::group(['prefix' => 'v1', 'middleware' => ['api', 'api-throttle:api']], fu
|
||||
]
|
||||
)->name('api.assets.restore');
|
||||
|
||||
Route::post('{asset}/files',
|
||||
[
|
||||
Api\AssetFilesController::class,
|
||||
'store'
|
||||
]
|
||||
)->name('api.assets.files.store');
|
||||
|
||||
Route::get('{asset}/files',
|
||||
[
|
||||
Api\AssetFilesController::class,
|
||||
'list'
|
||||
]
|
||||
)->name('api.assets.files.index');
|
||||
|
||||
Route::get('{asset_id}/file/{file_id}',
|
||||
[
|
||||
Api\AssetFilesController::class,
|
||||
'show'
|
||||
]
|
||||
)->name('api.assets.files.show');
|
||||
|
||||
Route::delete('{asset_id}/file/{file_id}',
|
||||
[
|
||||
Api\AssetFilesController::class,
|
||||
'destroy'
|
||||
]
|
||||
)->name('api.assets.files.destroy');
|
||||
|
||||
|
||||
|
||||
/** Begin assigned routes */
|
||||
Route::get('{asset}/assigned/assets',
|
||||
@ -853,33 +824,6 @@ Route::group(['prefix' => 'v1', 'middleware' => ['api', 'api-throttle:api']], fu
|
||||
]
|
||||
)->name('api.models.restore');
|
||||
|
||||
Route::post('{model_id}/files',
|
||||
[
|
||||
Api\AssetModelFilesController::class,
|
||||
'store'
|
||||
]
|
||||
)->name('api.models.files.store');
|
||||
|
||||
Route::get('{model_id}/files',
|
||||
[
|
||||
Api\AssetModelFilesController::class,
|
||||
'list'
|
||||
]
|
||||
)->name('api.models.files.index');
|
||||
|
||||
Route::get('{model_id}/file/{file_id}',
|
||||
[
|
||||
Api\AssetModelFilesController::class,
|
||||
'show'
|
||||
]
|
||||
)->name('api.models.files.show');
|
||||
|
||||
Route::delete('{model_id}/file/{file_id}',
|
||||
[
|
||||
Api\AssetModelFilesController::class,
|
||||
'destroy'
|
||||
]
|
||||
)->name('api.models.files.destroy');
|
||||
});
|
||||
|
||||
Route::resource('models',
|
||||
@ -1144,12 +1088,6 @@ Route::group(['prefix' => 'v1', 'middleware' => ['api', 'api-throttle:api']], fu
|
||||
]
|
||||
)->name('api.users.licenselist');
|
||||
|
||||
Route::post('{user}/upload',
|
||||
[
|
||||
Api\UsersController::class,
|
||||
'postUpload'
|
||||
]
|
||||
)->name('api.users.uploads');
|
||||
|
||||
Route::post('{user}/restore',
|
||||
[
|
||||
@ -1365,5 +1303,44 @@ Route::group(['prefix' => 'v1', 'middleware' => ['api', 'api-throttle:api']], fu
|
||||
])->name('api.assets.labels');
|
||||
// end generate label routes
|
||||
|
||||
/**
|
||||
* Uploaded files API routes
|
||||
*/
|
||||
|
||||
// List files
|
||||
Route::get('{object_type}/{id}/files',
|
||||
[
|
||||
Api\UploadedFilesController::class,
|
||||
'index'
|
||||
]
|
||||
)->name('api.files.index')
|
||||
->where(['object_type' => 'assets|models|users|locations|accessories|consumables|licenses|components']);
|
||||
|
||||
// Get a file
|
||||
Route::get('{object_type}/{id}/files/{file_id}',
|
||||
[
|
||||
Api\UploadedFilesController::class,
|
||||
'show'
|
||||
]
|
||||
)->name('api.files.show')
|
||||
->where(['object_type' => 'assets|models|users|locations|accessories|consumables|licenses|components']);
|
||||
|
||||
// Upload files(s)
|
||||
Route::post('{object_type}/{id}/files',
|
||||
[
|
||||
Api\UploadedFilesController::class,
|
||||
'store'
|
||||
]
|
||||
)->name('api.files.store')
|
||||
->where(['object_type' => 'assets|models|users|locations|accessories|consumables|licenses|components']);
|
||||
|
||||
// Delete files(s)
|
||||
Route::delete('{object_type}/{id}/files/{file_id}/delete',
|
||||
[
|
||||
Api\UploadedFilesController::class,
|
||||
'destroy'
|
||||
]
|
||||
)->name('api.files.destroy')
|
||||
->where(['object_type' => 'assets|models|users|locations|accessories|consumables|licenses|components']);
|
||||
|
||||
}); // end API routes
|
||||
|
||||
194
tests/Feature/Accessories/Api/AccessoryFilesTest.php
Normal file
194
tests/Feature/Accessories/Api/AccessoryFilesTest.php
Normal file
@ -0,0 +1,194 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Accessories\Api;
|
||||
|
||||
use App\Models\Accessory;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AccessoryFilesTest extends TestCase
|
||||
{
|
||||
public function testAccessoryApiAcceptsFileUpload()
|
||||
{
|
||||
// Upload a file to a model
|
||||
|
||||
// Create a model to work with
|
||||
$accessory = Accessory::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
//Upload a file
|
||||
$this->actingAsForApi($user)
|
||||
->post(
|
||||
route('api.files.store', ['object_type' => 'accessories', 'id' => $accessory->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)]
|
||||
])
|
||||
->assertOk();
|
||||
}
|
||||
|
||||
public function testAccessoryApiListsFiles()
|
||||
{
|
||||
// List all files on a model
|
||||
|
||||
// Create a model to work with
|
||||
$accessory = Accessory::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
// List the files
|
||||
$this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'accessories', 'id' => $accessory->id]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'rows',
|
||||
'total',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testAccessoryFailsIfInvalidTypePassedInUrl()
|
||||
{
|
||||
// List all files on a model
|
||||
|
||||
// Create an model to work with
|
||||
$accessory = Accessory::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
// List the files
|
||||
$this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'shibboleeeeeet', 'id' => $accessory->id]))
|
||||
->assertStatus(404);
|
||||
}
|
||||
|
||||
public function testAccessoryFailsIfInvalidIdPassedInUrl()
|
||||
{
|
||||
// List all files on a model
|
||||
|
||||
// Create an model to work with
|
||||
$accessory = Accessory::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
// List the files
|
||||
$this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'accessories', 'id' => 100000]))
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('error');
|
||||
}
|
||||
|
||||
public function testAccessoryApiDownloadsFile()
|
||||
{
|
||||
// Download a file from a model
|
||||
|
||||
// Create a model to work with
|
||||
$accessory = Accessory::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
// Upload a file
|
||||
$this->actingAsForApi($user)
|
||||
->post(
|
||||
route('api.files.store', ['object_type' => 'accessories', 'id' => $accessory->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)],
|
||||
])
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'status',
|
||||
'messages',
|
||||
]);
|
||||
|
||||
// Upload a file with notes
|
||||
$this->actingAsForApi($user)
|
||||
->post(
|
||||
route('api.files.store', ['object_type' => 'accessories', 'id' => $accessory->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)],
|
||||
'notes' => 'manual'
|
||||
])
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'status',
|
||||
'messages',
|
||||
]);
|
||||
|
||||
// List the files to get the file ID
|
||||
$result = $this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'accessories', 'id' => $accessory->id]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'total',
|
||||
'rows'=>[
|
||||
'*' => [
|
||||
'id',
|
||||
'filename',
|
||||
'url',
|
||||
'created_by',
|
||||
'created_at',
|
||||
'deleted_at',
|
||||
'note',
|
||||
'available_actions'
|
||||
]
|
||||
]
|
||||
])
|
||||
->assertJsonPath('rows.0.note',null)
|
||||
->assertJsonPath('rows.1.note','manual');
|
||||
|
||||
// Get the file
|
||||
$this->actingAsForApi($user)
|
||||
->get(
|
||||
route('api.files.show', [
|
||||
'object_type' => 'accessories',
|
||||
'id' => $accessory->id,
|
||||
'file_id' => $result->decodeResponseJson()->json()["rows"][0]["id"],
|
||||
]))
|
||||
->assertOk();
|
||||
}
|
||||
|
||||
public function testAccessoryApiDeletesFile()
|
||||
{
|
||||
// Delete a file from a model
|
||||
|
||||
// Create a model to work with
|
||||
$accessory = Accessory::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
//Upload a file
|
||||
$this->actingAsForApi($user)
|
||||
->post(
|
||||
route('api.files.store', ['object_type' => 'accessories', 'id' => $accessory->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)]
|
||||
])
|
||||
->assertOk();
|
||||
|
||||
// List the files to get the file ID
|
||||
$result = $this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'accessories', 'id' => $accessory->id]))
|
||||
->assertOk();
|
||||
|
||||
// Delete the file
|
||||
$this->actingAsForApi($user)
|
||||
->delete(
|
||||
route('api.files.destroy', [
|
||||
'object_type' => 'accessories',
|
||||
'id' => $accessory->id,
|
||||
'file_id' => $result->decodeResponseJson()->json()["rows"][0]["id"],
|
||||
]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'status',
|
||||
'messages',
|
||||
]);
|
||||
}
|
||||
}
|
||||
@ -14,39 +14,74 @@ class AssetModelFilesTest extends TestCase
|
||||
// Upload a file to a model
|
||||
|
||||
// Create a model to work with
|
||||
$model = AssetModel::factory()->count(1)->create();
|
||||
$model = AssetModel::factory()->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.models.files.store', ['model_id' => $model[0]["id"]]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)]
|
||||
])
|
||||
->assertOk();
|
||||
route('api.files.store', ['object_type' => 'models', 'id' => $model->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)]
|
||||
])
|
||||
->assertOk();
|
||||
}
|
||||
|
||||
public function testAssetModelApiListsFiles()
|
||||
{
|
||||
// List all files on a model
|
||||
|
||||
|
||||
// Create an model to work with
|
||||
$model = AssetModel::factory()->count(1)->create();
|
||||
$model = AssetModel::factory()->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)
|
||||
// List the files
|
||||
$this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.models.files.index', ['model_id' => $model[0]["id"]]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'rows',
|
||||
'total',
|
||||
]);
|
||||
route('api.files.index', ['object_type' => 'models', 'id' => $model->id]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'rows',
|
||||
'total',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testAssetModelFailsIfInvalidTypePassedInUrl()
|
||||
{
|
||||
// List all files on a model
|
||||
|
||||
// Create an model to work with
|
||||
$model = AssetModel::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
// List the files
|
||||
$this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'shibboleeeeeet', 'id' => $model->id]))
|
||||
->assertStatus(404);
|
||||
}
|
||||
|
||||
public function testAssetModelFailsIfInvalidIdPassedInUrl()
|
||||
{
|
||||
// List all files on a model
|
||||
|
||||
// Create an model to work with
|
||||
$model = AssetModel::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
// List the files
|
||||
$this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'models', 'id' => 100000]))
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('error');
|
||||
}
|
||||
|
||||
public function testAssetModelApiDownloadsFile()
|
||||
@ -54,40 +89,40 @@ class AssetModelFilesTest extends TestCase
|
||||
// Download a file from a model
|
||||
|
||||
// Create a model to work with
|
||||
$model = AssetModel::factory()->count(1)->create();
|
||||
$model = AssetModel::factory()->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.models.files.store', ['model_id' => $model[0]["id"]]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)],
|
||||
])
|
||||
route('api.files.store', ['object_type' => 'models', 'id' => $model->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)],
|
||||
])
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'status',
|
||||
'messages',
|
||||
]);
|
||||
|
||||
// Upload a file with notes
|
||||
$this->actingAsForApi($user)
|
||||
// Upload a file with notes
|
||||
$this->actingAsForApi($user)
|
||||
->post(
|
||||
route('api.models.files.store', ['model_id' => $model[0]["id"]]), [
|
||||
route('api.files.store', ['object_type' => 'models', 'id' => $model->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)],
|
||||
'notes' => 'manual'
|
||||
])
|
||||
])
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'status',
|
||||
'messages',
|
||||
]);
|
||||
|
||||
// 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.models.files.index', ['model_id' => $model[0]["id"]]))
|
||||
route('api.files.index', ['object_type' => 'models', 'id' => $model->id]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'total',
|
||||
@ -98,26 +133,24 @@ class AssetModelFilesTest extends TestCase
|
||||
'url',
|
||||
'created_by',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
'deleted_at',
|
||||
'note',
|
||||
'available_actions'
|
||||
]
|
||||
]
|
||||
])
|
||||
->assertJsonPath('rows.0.note','')
|
||||
->assertJsonPath('rows.0.note',null)
|
||||
->assertJsonPath('rows.1.note','manual');
|
||||
|
||||
|
||||
|
||||
// Get the file
|
||||
$this->actingAsForApi($user)
|
||||
// Get the file
|
||||
$this->actingAsForApi($user)
|
||||
->get(
|
||||
route('api.models.files.show', [
|
||||
'model_id' => $model[0]["id"],
|
||||
'file_id' => $result->decodeResponseJson()->json()["rows"][0]["id"],
|
||||
]))
|
||||
->assertOk();
|
||||
route('api.files.show', [
|
||||
'object_type' => 'models',
|
||||
'id' => $model->id,
|
||||
'file_id' => $result->decodeResponseJson()->json()["rows"][0]["id"],
|
||||
]))
|
||||
->assertOk();
|
||||
}
|
||||
|
||||
public function testAssetModelApiDeletesFile()
|
||||
@ -125,36 +158,37 @@ class AssetModelFilesTest extends TestCase
|
||||
// Delete a file from a model
|
||||
|
||||
// Create a model to work with
|
||||
$model = AssetModel::factory()->count(1)->create();
|
||||
$model = AssetModel::factory()->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.models.files.store', ['model_id' => $model[0]["id"]]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)]
|
||||
])
|
||||
->assertOk();
|
||||
route('api.files.store', ['object_type' => 'models', 'id' => $model->id]), [
|
||||
'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.models.files.index', ['model_id' => $model[0]["id"]]))
|
||||
->assertOk();
|
||||
route('api.files.index', ['object_type' => 'models', 'id' => $model->id]))
|
||||
->assertOk();
|
||||
|
||||
// Delete the file
|
||||
$this->actingAsForApi($user)
|
||||
// Delete the file
|
||||
$this->actingAsForApi($user)
|
||||
->delete(
|
||||
route('api.models.files.destroy', [
|
||||
'model_id' => $model[0]["id"],
|
||||
'file_id' => $result->decodeResponseJson()->json()["rows"][0]["id"],
|
||||
]))
|
||||
->assertOk()
|
||||
route('api.files.destroy', [
|
||||
'object_type' => 'models',
|
||||
'id' => $model->id,
|
||||
'file_id' => $result->decodeResponseJson()->json()["rows"][0]["id"],
|
||||
]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'status',
|
||||
'messages',
|
||||
]);
|
||||
'status',
|
||||
'messages',
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -14,7 +14,7 @@ class AssetFilesTest extends TestCase
|
||||
// Upload a file to an asset
|
||||
|
||||
// Create an asset to work with
|
||||
$asset = Asset::factory()->count(1)->create();
|
||||
$asset = Asset::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
@ -22,30 +22,30 @@ class AssetFilesTest extends TestCase
|
||||
//Upload a file
|
||||
$this->actingAsForApi($user)
|
||||
->post(
|
||||
route('api.assets.files.store', $asset), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)]
|
||||
])
|
||||
->assertOk();
|
||||
route('api.files.store', ['object_type' => 'assets', 'id' => $asset->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)]
|
||||
])
|
||||
->assertOk();
|
||||
}
|
||||
|
||||
public function testAssetApiListsFiles()
|
||||
{
|
||||
// List all files on an asset
|
||||
|
||||
|
||||
// Create an asset to work with
|
||||
$asset = Asset::factory()->count(1)->create();
|
||||
$asset = Asset::factory()->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))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'rows',
|
||||
'total',
|
||||
]);
|
||||
->getJson(route('api.files.index', ['object_type' => 'assets', 'id' => $asset->id]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'rows',
|
||||
'total',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testAssetApiDownloadsFile()
|
||||
@ -53,21 +53,21 @@ class AssetFilesTest extends TestCase
|
||||
// Download a file from an asset
|
||||
|
||||
// Create an asset to work with
|
||||
$asset = Asset::factory()->count(1)->create();
|
||||
$asset = Asset::factory()->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), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)]
|
||||
])
|
||||
->post(route('api.files.store', ['object_type' => 'assets', 'id' => $asset->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)]
|
||||
])
|
||||
->assertOk();
|
||||
|
||||
// List the files to get the file ID
|
||||
$result = $this->actingAsForApi($user)
|
||||
->getJson(route('api.assets.files.index', $asset))
|
||||
->getJson(route('api.files.index', ['object_type' => 'assets', 'id' => $asset->id]))
|
||||
->assertOk();
|
||||
}
|
||||
|
||||
@ -76,7 +76,7 @@ class AssetFilesTest extends TestCase
|
||||
// Delete a file from an asset
|
||||
|
||||
// Create an asset to work with
|
||||
$asset = Asset::factory()->count(1)->create();
|
||||
$asset = Asset::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
@ -84,16 +84,16 @@ class AssetFilesTest extends TestCase
|
||||
//Upload a file
|
||||
$this->actingAsForApi($user)
|
||||
->post(
|
||||
route('api.assets.files.store', $asset), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)]
|
||||
])
|
||||
->assertOk();
|
||||
route('api.files.store', ['object_type' => 'assets', 'id' => $asset->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)]
|
||||
])
|
||||
->assertOk();
|
||||
|
||||
// List the files to get the file ID
|
||||
$result = $this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.assets.files.index', $asset))
|
||||
->assertOk();
|
||||
|
||||
route('api.files.index', ['object_type' => 'assets', 'id' => $asset->id]))
|
||||
->assertOk();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
192
tests/Feature/Components/Api/ComponentFileTest.php
Normal file
192
tests/Feature/Components/Api/ComponentFileTest.php
Normal file
@ -0,0 +1,192 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Components\Api;
|
||||
|
||||
use App\Models\Component;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ComponentFileTest extends TestCase
|
||||
{
|
||||
public function testComponentApiAcceptsFileUpload()
|
||||
{
|
||||
// Create a model to work with
|
||||
$component = Component::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
//Upload a file
|
||||
$this->actingAsForApi($user)
|
||||
->post(
|
||||
route('api.files.store', ['object_type' => 'components', 'id' => $component->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)]
|
||||
])
|
||||
->assertOk();
|
||||
}
|
||||
|
||||
public function testComponentApiListsFiles()
|
||||
{
|
||||
// List all files on a model
|
||||
|
||||
// Create a model to work with
|
||||
$component = Component::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
// List the files
|
||||
$this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'components', 'id' => $component->id]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'rows',
|
||||
'total',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testComponentFailsIfInvalidTypePassedInUrl()
|
||||
{
|
||||
// List all files on a model
|
||||
|
||||
// Create an model to work with
|
||||
$component = Component::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
// List the files
|
||||
$this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'shibboleeeeeet', 'id' => $component->id]))
|
||||
->assertStatus(404);
|
||||
}
|
||||
|
||||
public function testComponentFailsIfInvalidIdPassedInUrl()
|
||||
{
|
||||
// List all files on a model
|
||||
|
||||
// Create an model to work with
|
||||
$component = Component::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
// List the files
|
||||
$this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'components', 'id' => 100000]))
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('error');
|
||||
}
|
||||
|
||||
public function testComponentApiDownloadsFile()
|
||||
{
|
||||
// Download a file from a model
|
||||
|
||||
// Create a model to work with
|
||||
$component = Component::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
// Upload a file
|
||||
$this->actingAsForApi($user)
|
||||
->post(
|
||||
route('api.files.store', ['object_type' => 'components', 'id' => $component->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)],
|
||||
])
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'status',
|
||||
'messages',
|
||||
]);
|
||||
|
||||
// Upload a file with notes
|
||||
$this->actingAsForApi($user)
|
||||
->post(
|
||||
route('api.files.store', ['object_type' => 'components', 'id' => $component->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)],
|
||||
'notes' => 'manual'
|
||||
])
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'status',
|
||||
'messages',
|
||||
]);
|
||||
|
||||
// List the files to get the file ID
|
||||
$result = $this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'components', 'id' => $component->id]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'total',
|
||||
'rows'=>[
|
||||
'*' => [
|
||||
'id',
|
||||
'filename',
|
||||
'url',
|
||||
'created_by',
|
||||
'created_at',
|
||||
'deleted_at',
|
||||
'note',
|
||||
'available_actions'
|
||||
]
|
||||
]
|
||||
])
|
||||
->assertJsonPath('rows.0.note',null)
|
||||
->assertJsonPath('rows.1.note','manual');
|
||||
|
||||
// Get the file
|
||||
$this->actingAsForApi($user)
|
||||
->get(
|
||||
route('api.files.show', [
|
||||
'object_type' => 'components',
|
||||
'id' => $component->id,
|
||||
'file_id' => $result->decodeResponseJson()->json()["rows"][0]["id"],
|
||||
]))
|
||||
->assertOk();
|
||||
}
|
||||
|
||||
public function testComponentApiDeletesFile()
|
||||
{
|
||||
// Delete a file from a model
|
||||
|
||||
// Create a model to work with
|
||||
$component = Component::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
//Upload a file
|
||||
$this->actingAsForApi($user)
|
||||
->post(
|
||||
route('api.files.store', ['object_type' => 'components', 'id' => $component->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)]
|
||||
])
|
||||
->assertOk();
|
||||
|
||||
// List the files to get the file ID
|
||||
$result = $this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'components', 'id' => $component->id]))
|
||||
->assertOk();
|
||||
|
||||
// Delete the file
|
||||
$this->actingAsForApi($user)
|
||||
->delete(
|
||||
route('api.files.destroy', [
|
||||
'object_type' => 'components',
|
||||
'id' => $component->id,
|
||||
'file_id' => $result->decodeResponseJson()->json()["rows"][0]["id"],
|
||||
]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'status',
|
||||
'messages',
|
||||
]);
|
||||
}
|
||||
}
|
||||
194
tests/Feature/Consumables/Api/ConsumableFileTest.php
Normal file
194
tests/Feature/Consumables/Api/ConsumableFileTest.php
Normal file
@ -0,0 +1,194 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Consumables\Api;
|
||||
|
||||
use App\Models\Consumable;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ConsumableFileTest extends TestCase
|
||||
{
|
||||
public function testConsumableApiAcceptsFileUpload()
|
||||
{
|
||||
// Upload a file to a model
|
||||
|
||||
// Create a model to work with
|
||||
$consumable = Consumable::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
//Upload a file
|
||||
$this->actingAsForApi($user)
|
||||
->post(
|
||||
route('api.files.store', ['object_type' => 'consumables', 'id' => $consumable->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)]
|
||||
])
|
||||
->assertOk();
|
||||
}
|
||||
|
||||
public function testConsumableApiListsFiles()
|
||||
{
|
||||
// List all files on a model
|
||||
|
||||
// Create a model to work with
|
||||
$consumable = Consumable::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
// List the files
|
||||
$this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'consumables', 'id' => $consumable->id]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'rows',
|
||||
'total',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testConsumableFailsIfInvalidTypePassedInUrl()
|
||||
{
|
||||
// List all files on a model
|
||||
|
||||
// Create an model to work with
|
||||
$consumable = Consumable::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
// List the files
|
||||
$this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'shibboleeeeeet', 'id' => $consumable->id]))
|
||||
->assertStatus(404);
|
||||
}
|
||||
|
||||
public function testConsumableFailsIfInvalidIdPassedInUrl()
|
||||
{
|
||||
// List all files on a model
|
||||
|
||||
// Create an model to work with
|
||||
$consumable = Consumable::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
// List the files
|
||||
$this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'consumables', 'id' => 100000]))
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('error');
|
||||
}
|
||||
|
||||
public function testConsumableApiDownloadsFile()
|
||||
{
|
||||
// Download a file from a model
|
||||
|
||||
// Create a model to work with
|
||||
$consumable = Consumable::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
// Upload a file
|
||||
$this->actingAsForApi($user)
|
||||
->post(
|
||||
route('api.files.store', ['object_type' => 'consumables', 'id' => $consumable->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)],
|
||||
])
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'status',
|
||||
'messages',
|
||||
]);
|
||||
|
||||
// Upload a file with notes
|
||||
$this->actingAsForApi($user)
|
||||
->post(
|
||||
route('api.files.store', ['object_type' => 'consumables', 'id' => $consumable->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)],
|
||||
'notes' => 'manual'
|
||||
])
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'status',
|
||||
'messages',
|
||||
]);
|
||||
|
||||
// List the files to get the file ID
|
||||
$result = $this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'consumables', 'id' => $consumable->id]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'total',
|
||||
'rows'=>[
|
||||
'*' => [
|
||||
'id',
|
||||
'filename',
|
||||
'url',
|
||||
'created_by',
|
||||
'created_at',
|
||||
'deleted_at',
|
||||
'note',
|
||||
'available_actions'
|
||||
]
|
||||
]
|
||||
])
|
||||
->assertJsonPath('rows.0.note',null)
|
||||
->assertJsonPath('rows.1.note','manual');
|
||||
|
||||
// Get the file
|
||||
$this->actingAsForApi($user)
|
||||
->get(
|
||||
route('api.files.show', [
|
||||
'object_type' => 'consumables',
|
||||
'id' => $consumable->id,
|
||||
'file_id' => $result->decodeResponseJson()->json()["rows"][0]["id"],
|
||||
]))
|
||||
->assertOk();
|
||||
}
|
||||
|
||||
public function testConsumableApiDeletesFile()
|
||||
{
|
||||
// Delete a file from a model
|
||||
|
||||
// Create a model to work with
|
||||
$consumable = Consumable::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
//Upload a file
|
||||
$this->actingAsForApi($user)
|
||||
->post(
|
||||
route('api.files.store', ['object_type' => 'consumables', 'id' => $consumable->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)]
|
||||
])
|
||||
->assertOk();
|
||||
|
||||
// List the files to get the file ID
|
||||
$result = $this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'consumables', 'id' => $consumable->id]))
|
||||
->assertOk();
|
||||
|
||||
// Delete the file
|
||||
$this->actingAsForApi($user)
|
||||
->delete(
|
||||
route('api.files.destroy', [
|
||||
'object_type' => 'consumables',
|
||||
'id' => $consumable->id,
|
||||
'file_id' => $result->decodeResponseJson()->json()["rows"][0]["id"],
|
||||
]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'status',
|
||||
'messages',
|
||||
]);
|
||||
}
|
||||
}
|
||||
194
tests/Feature/Licenses/Api/LicenseUploadTest.php
Normal file
194
tests/Feature/Licenses/Api/LicenseUploadTest.php
Normal file
@ -0,0 +1,194 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Licenses\Api;
|
||||
|
||||
use App\Models\License;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Tests\TestCase;
|
||||
|
||||
class LicenseUploadTest extends TestCase
|
||||
{
|
||||
public function testLicenseApiAcceptsFileUpload()
|
||||
{
|
||||
// Upload a file to a model
|
||||
|
||||
// Create a model to work with
|
||||
$license = License::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
//Upload a file
|
||||
$this->actingAsForApi($user)
|
||||
->post(
|
||||
route('api.files.store', ['object_type' => 'licenses', 'id' => $license->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)]
|
||||
])
|
||||
->assertOk();
|
||||
}
|
||||
|
||||
public function testLicenseApiListsFiles()
|
||||
{
|
||||
// List all files on a model
|
||||
|
||||
// Create an model to work with
|
||||
$license = License::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
// List the files
|
||||
$this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'licenses', 'id' => $license->id]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'rows',
|
||||
'total',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testLicenseFailsIfInvalidTypePassedInUrl()
|
||||
{
|
||||
// List all files on a model
|
||||
|
||||
// Create an model to work with
|
||||
$license = License::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
// List the files
|
||||
$this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'shibboleeeeeet', 'id' => $license->id]))
|
||||
->assertStatus(404);
|
||||
}
|
||||
|
||||
public function testLicenseFailsIfInvalidIdPassedInUrl()
|
||||
{
|
||||
// List all files on a model
|
||||
|
||||
// Create an model to work with
|
||||
$license = License::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
// List the files
|
||||
$this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'licenses', 'id' => 100000]))
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('error');
|
||||
}
|
||||
|
||||
public function testLicenseApiDownloadsFile()
|
||||
{
|
||||
// Download a file from a model
|
||||
|
||||
// Create a model to work with
|
||||
$license = License::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
// Upload a file
|
||||
$this->actingAsForApi($user)
|
||||
->post(
|
||||
route('api.files.store', ['object_type' => 'licenses', 'id' => $license->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)],
|
||||
])
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'status',
|
||||
'messages',
|
||||
]);
|
||||
|
||||
// Upload a file with notes
|
||||
$this->actingAsForApi($user)
|
||||
->post(
|
||||
route('api.files.store', ['object_type' => 'licenses', 'id' => $license->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)],
|
||||
'notes' => 'manual'
|
||||
])
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'status',
|
||||
'messages',
|
||||
]);
|
||||
|
||||
// List the files to get the file ID
|
||||
$result = $this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'licenses', 'id' => $license->id]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'total',
|
||||
'rows'=>[
|
||||
'*' => [
|
||||
'id',
|
||||
'filename',
|
||||
'url',
|
||||
'created_by',
|
||||
'created_at',
|
||||
'deleted_at',
|
||||
'note',
|
||||
'available_actions'
|
||||
]
|
||||
]
|
||||
])
|
||||
->assertJsonPath('rows.0.note',null)
|
||||
->assertJsonPath('rows.1.note','manual');
|
||||
|
||||
// Get the file
|
||||
$this->actingAsForApi($user)
|
||||
->get(
|
||||
route('api.files.show', [
|
||||
'object_type' => 'licenses',
|
||||
'id' => $license->id,
|
||||
'file_id' => $result->decodeResponseJson()->json()["rows"][0]["id"],
|
||||
]))
|
||||
->assertOk();
|
||||
}
|
||||
|
||||
public function testLicenseApiDeletesFile()
|
||||
{
|
||||
// Delete a file from a model
|
||||
|
||||
// Create a model to work with
|
||||
$license = License::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
//Upload a file
|
||||
$this->actingAsForApi($user)
|
||||
->post(
|
||||
route('api.files.store', ['object_type' => 'licenses', 'id' => $license->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)]
|
||||
])
|
||||
->assertOk();
|
||||
|
||||
// List the files to get the file ID
|
||||
$result = $this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'licenses', 'id' => $license->id]))
|
||||
->assertOk();
|
||||
|
||||
// Delete the file
|
||||
$this->actingAsForApi($user)
|
||||
->delete(
|
||||
route('api.files.destroy', [
|
||||
'object_type' => 'licenses',
|
||||
'id' => $license->id,
|
||||
'file_id' => $result->decodeResponseJson()->json()["rows"][0]["id"],
|
||||
]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'status',
|
||||
'messages',
|
||||
]);
|
||||
}
|
||||
}
|
||||
192
tests/Feature/Locations/Api/LocationFileTest.php
Normal file
192
tests/Feature/Locations/Api/LocationFileTest.php
Normal file
@ -0,0 +1,192 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Locations\Api;
|
||||
|
||||
use App\Models\Location;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Tests\TestCase;
|
||||
|
||||
class LocationFileTest extends TestCase
|
||||
{
|
||||
public function testLocationApiAcceptsFileUpload()
|
||||
{
|
||||
// Create a model to work with
|
||||
$location = Location::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
//Upload a file
|
||||
$this->actingAsForApi($user)
|
||||
->post(
|
||||
route('api.files.store', ['object_type' => 'locations', 'id' => $location->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)]
|
||||
])
|
||||
->assertOk();
|
||||
}
|
||||
|
||||
public function testLocationApiListsFiles()
|
||||
{
|
||||
// List all files on a model
|
||||
|
||||
// Create a model to work with
|
||||
$location = Location::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
// List the files
|
||||
$this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'locations', 'id' => $location->id]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'rows',
|
||||
'total',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testLocationFailsIfInvalidTypePassedInUrl()
|
||||
{
|
||||
// List all files on a model
|
||||
|
||||
// Create an model to work with
|
||||
$location = Location::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
// List the files
|
||||
$this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'shibboleeeeeet', 'id' => $location->id]))
|
||||
->assertStatus(404);
|
||||
}
|
||||
|
||||
public function testLocationFailsIfInvalidIdPassedInUrl()
|
||||
{
|
||||
// List all files on a model
|
||||
|
||||
// Create an model to work with
|
||||
$location = Location::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
// List the files
|
||||
$this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'locations', 'id' => 100000]))
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('error');
|
||||
}
|
||||
|
||||
public function testLocationApiDownloadsFile()
|
||||
{
|
||||
// Download a file from a model
|
||||
|
||||
// Create a model to work with
|
||||
$location = Location::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
// Upload a file
|
||||
$this->actingAsForApi($user)
|
||||
->post(
|
||||
route('api.files.store', ['object_type' => 'locations', 'id' => $location->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)],
|
||||
])
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'status',
|
||||
'messages',
|
||||
]);
|
||||
|
||||
// Upload a file with notes
|
||||
$this->actingAsForApi($user)
|
||||
->post(
|
||||
route('api.files.store', ['object_type' => 'locations', 'id' => $location->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)],
|
||||
'notes' => 'manual'
|
||||
])
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'status',
|
||||
'messages',
|
||||
]);
|
||||
|
||||
// List the files to get the file ID
|
||||
$result = $this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'locations', 'id' => $location->id]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'total',
|
||||
'rows'=>[
|
||||
'*' => [
|
||||
'id',
|
||||
'filename',
|
||||
'url',
|
||||
'created_by',
|
||||
'created_at',
|
||||
'deleted_at',
|
||||
'note',
|
||||
'available_actions'
|
||||
]
|
||||
]
|
||||
])
|
||||
->assertJsonPath('rows.0.note',null)
|
||||
->assertJsonPath('rows.1.note','manual');
|
||||
|
||||
// Get the file
|
||||
$this->actingAsForApi($user)
|
||||
->get(
|
||||
route('api.files.show', [
|
||||
'object_type' => 'locations',
|
||||
'id' => $location->id,
|
||||
'file_id' => $result->decodeResponseJson()->json()["rows"][0]["id"],
|
||||
]))
|
||||
->assertOk();
|
||||
}
|
||||
|
||||
public function testLocationApiDeletesFile()
|
||||
{
|
||||
// Delete a file from a model
|
||||
|
||||
// Create a model to work with
|
||||
$location = Location::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$user = User::factory()->superuser()->create();
|
||||
|
||||
//Upload a file
|
||||
$this->actingAsForApi($user)
|
||||
->post(
|
||||
route('api.files.store', ['object_type' => 'locations', 'id' => $location->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)]
|
||||
])
|
||||
->assertOk();
|
||||
|
||||
// List the files to get the file ID
|
||||
$result = $this->actingAsForApi($user)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'locations', 'id' => $location->id]))
|
||||
->assertOk();
|
||||
|
||||
// Delete the file
|
||||
$this->actingAsForApi($user)
|
||||
->delete(
|
||||
route('api.files.destroy', [
|
||||
'object_type' => 'locations',
|
||||
'id' => $location->id,
|
||||
'file_id' => $result->decodeResponseJson()->json()["rows"][0]["id"],
|
||||
]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'status',
|
||||
'messages',
|
||||
]);
|
||||
}
|
||||
}
|
||||
191
tests/Feature/Users/Api/UserFileTest.php
Normal file
191
tests/Feature/Users/Api/UserFileTest.php
Normal file
@ -0,0 +1,191 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Users\Api;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Tests\TestCase;
|
||||
|
||||
class UserFileTest extends TestCase
|
||||
{
|
||||
public function testUserApiAcceptsFileUpload()
|
||||
{
|
||||
// Create a model to work with
|
||||
$user = User::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$admin = User::factory()->superuser()->create();
|
||||
|
||||
//Upload a file
|
||||
$this->actingAsForApi($admin)
|
||||
->post(
|
||||
route('api.files.store', ['object_type' => 'users', 'id' => $user->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)]
|
||||
])
|
||||
->assertOk();
|
||||
}
|
||||
|
||||
public function testUserApiListsFiles()
|
||||
{
|
||||
// List all files on a model
|
||||
|
||||
// Create a model to work with
|
||||
$user = User::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$admin = User::factory()->superuser()->create();
|
||||
|
||||
// List the files
|
||||
$this->actingAsForApi($admin)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'users', 'id' => $user->id]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'rows',
|
||||
'total',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testUserFailsIfInvalidTypePassedInUrl()
|
||||
{
|
||||
// List all files on a model
|
||||
|
||||
// Create an model to work with
|
||||
$user = User::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$admin = User::factory()->superuser()->create();
|
||||
|
||||
// List the files
|
||||
$this->actingAsForApi($admin)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'shibboleeeeeet', 'id' => $user->id]))
|
||||
->assertStatus(404);
|
||||
}
|
||||
|
||||
public function testUserFailsIfInvalidIdPassedInUrl()
|
||||
{
|
||||
// List all files on a model
|
||||
|
||||
// Create an model to work with
|
||||
$user = User::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$admin = User::factory()->superuser()->create();
|
||||
|
||||
// List the files
|
||||
$this->actingAsForApi($admin)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'users', 'id' => 100000]))
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('error');
|
||||
}
|
||||
|
||||
public function testUserApiDownloadsFile()
|
||||
{
|
||||
// Download a file from a model
|
||||
|
||||
// Create a model to work with
|
||||
$user = User::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$admin = User::factory()->superuser()->create();
|
||||
|
||||
// Upload a file
|
||||
$this->actingAsForApi($admin)
|
||||
->post(
|
||||
route('api.files.store', ['object_type' => 'users', 'id' => $user->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)],
|
||||
])
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'status',
|
||||
'messages',
|
||||
]);
|
||||
|
||||
// Upload a file with notes
|
||||
$this->actingAsForApi($admin)
|
||||
->post(
|
||||
route('api.files.store', ['object_type' => 'users', 'id' => $user->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)],
|
||||
'notes' => 'manual'
|
||||
])
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'status',
|
||||
'messages',
|
||||
]);
|
||||
|
||||
// List the files to get the file ID
|
||||
$result = $this->actingAsForApi($admin)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'users', 'id' => $user->id]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'total',
|
||||
'rows'=>[
|
||||
'*' => [
|
||||
'id',
|
||||
'filename',
|
||||
'url',
|
||||
'created_by',
|
||||
'created_at',
|
||||
'deleted_at',
|
||||
'note',
|
||||
'available_actions'
|
||||
]
|
||||
]
|
||||
])
|
||||
->assertJsonPath('rows.0.note',null)
|
||||
->assertJsonPath('rows.1.note','manual');
|
||||
|
||||
// Get the file
|
||||
$this->actingAsForApi($admin)
|
||||
->get(
|
||||
route('api.files.show', [
|
||||
'object_type' => 'users',
|
||||
'id' => $user->id,
|
||||
'file_id' => $result->decodeResponseJson()->json()["rows"][0]["id"],
|
||||
]))
|
||||
->assertOk();
|
||||
}
|
||||
|
||||
public function testUserApiDeletesFile()
|
||||
{
|
||||
// Delete a file from a model
|
||||
|
||||
// Create a model to work with
|
||||
$user = User::factory()->create();
|
||||
|
||||
// Create a superuser to run this as
|
||||
$admin = User::factory()->superuser()->create();
|
||||
|
||||
//Upload a file
|
||||
$this->actingAsForApi($admin)
|
||||
->post(
|
||||
route('api.files.store', ['object_type' => 'users', 'id' => $user->id]), [
|
||||
'file' => [UploadedFile::fake()->create("test.jpg", 100)]
|
||||
])
|
||||
->assertOk();
|
||||
|
||||
// List the files to get the file ID
|
||||
$result = $this->actingAsForApi($admin)
|
||||
->getJson(
|
||||
route('api.files.index', ['object_type' => 'users', 'id' => $user->id]))
|
||||
->assertOk();
|
||||
|
||||
// Delete the file
|
||||
$this->actingAsForApi($admin)
|
||||
->delete(
|
||||
route('api.files.destroy', [
|
||||
'object_type' => 'users',
|
||||
'id' => $user->id,
|
||||
'file_id' => $result->decodeResponseJson()->json()["rows"][0]["id"],
|
||||
]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'status',
|
||||
'messages',
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user