diff --git a/app/Http/Controllers/FileController.php b/app/Http/Controllers/FileController.php index ad737a1..86d9a76 100644 --- a/app/Http/Controllers/FileController.php +++ b/app/Http/Controllers/FileController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers; use App\Http\Requests\FileStoreRequest; +use App\Http\Requests\FileUpdateRequest; use App\Http\Resources\FileResource; use App\Image\ImageProcessor; use App\Jobs\FileConversionQueue; @@ -22,19 +23,19 @@ class FileController extends Controller if ($request->castParams == 'resource') { return new FileResource(app()->file); } - if (!is_null(array_intersect(array_keys($request->all()), $this->availableParams))) { $imageProcessor->process(app()->file->getPath(), app()->file->getModifiedPath(), $request->all()); return response()->file(app()->file->getModifiedPath()); } - return response()->file(app()->file->getPath()); } - public function private($collection, $path) - { - Storage::disk('local')->download($path); - } + + // for local private we didn't talk about it + // public function private($collection, $path) + // { + // Storage::disk('local')->download($path); + // } public function store(FileStoreRequest $request, ImageProcessor $imageProcessor) { @@ -43,9 +44,8 @@ class FileController extends Controller $request->file = $imageProcessor->process($request->file->path(), '/tmp/' . app()->uuid . '.' . app()->collection->ext, app()->collection->process); } - $fileResource = null; - DB::transaction(function () use ($request,&$fileResource) { + DB::transaction(function () use ($request, &$fileResource) { $uuid = app()->uuid; $fileResource = File::create([ 'uuid' => $uuid, @@ -77,13 +77,17 @@ class FileController extends Controller return new FileResource($fileResource); } - public function update(Request $request, $id) + public function update(FileUpdateRequest $request) { - // + app()->file->update($request->all()); + return new FileResource(app()->file); } - public function destroy($id) + public function destroy() { - // + if (app()->file->trashed()) { + return app()->file->restore(); + } + return app()->file->delete(); } } diff --git a/app/Http/Middleware/BindCollectionModelMiddleware.php b/app/Http/Middleware/BindCollectionModelMiddleware.php index 460a9fb..c5bcb34 100644 --- a/app/Http/Middleware/BindCollectionModelMiddleware.php +++ b/app/Http/Middleware/BindCollectionModelMiddleware.php @@ -18,7 +18,7 @@ class BindCollectionModelMiddleware */ public function handle(Request $request, Closure $next) { - if (($request->route()->action['as'] == 'api.files.store') || ($request->route()->action['as'] == "api.files.show")) { + if (($request->route()->action['as'] == 'api.files.store') || ($request->route()->action['as'] == "api.files.show") || ($request->route()->action['as'] == 'api.files.update')) { app()->singleton('collection', function () use ($request) { return Collection::where('name', $request->route('collection_name'))->firstOrFail(); }); diff --git a/app/Http/Middleware/BindFileModelMiddleware.php b/app/Http/Middleware/BindFileModelMiddleware.php index 854a13b..d83d258 100644 --- a/app/Http/Middleware/BindFileModelMiddleware.php +++ b/app/Http/Middleware/BindFileModelMiddleware.php @@ -44,6 +44,30 @@ class BindFileModelMiddleware } } + if ($request->route()->action['as'] == 'api.files.update') { + $file = File::findOrFail($request->route('uuid')); + $Collection = Collection::where('name', $request->route('collection_name'))->firstOrFail(); + if (Storage::disk($Collection->disk)->exists($file->server_path . $file->uuid . '.' . $Collection->ext)) { + app()->bind('file', function () use ($file) { + return $file; + }); + }else{ + abort(404); + } + } + + if ($request->route()->action['as'] == 'api.files.destroy') { + $file = File::findOrFail($request->route('uuid')); + $Collection = Collection::withTrashed()->where('name', $request->route('collection_name'))->firstOrFail(); + if (Storage::disk($Collection->disk)->exists($file->server_path . $file->uuid . '.' . $Collection->ext)) { + app()->bind('file', function () use ($file) { + return $file; + }); + }else{ + abort(404); + } + } + return $next($request); } } diff --git a/app/Http/Requests/FileStoreRequest.php b/app/Http/Requests/FileStoreRequest.php index 8fdb029..5ec532e 100644 --- a/app/Http/Requests/FileStoreRequest.php +++ b/app/Http/Requests/FileStoreRequest.php @@ -30,7 +30,7 @@ class FileStoreRequest extends FormRequest return false; } - if (app()->collection->count !== 1 && (app()->collection->count <= File::where('user_id', auth()->id())->where('collction_id',app()->collection->id)->count()) && !app()->collection->tmp_support) { + if (app()->collection->count !== 1 && (app()->collection->count <= File::where('user_id', auth()->id())->where('collection_id',app()->collection->id)->count()) && !app()->collection->tmp_support) { return false; } if (!app()->bound('file') && is_null($this->file('file'))) { @@ -65,7 +65,6 @@ class FileStoreRequest extends FormRequest "alts.*" => [app()->collection->alt_required ? "required" : "nullable", 'max:1000'], "description" => [app()->collection->description_required ? "required" : "nullable", 'max:300'], 'original_name' => ["string", "nullable", 'max:300'], - 'public' => ['boolean', 'nullable'], 'published_at' => ['date_format:Y-m-d H:i:s', 'nullable'], ]; } diff --git a/app/Http/Requests/FileUpdateRequest.php b/app/Http/Requests/FileUpdateRequest.php new file mode 100644 index 0000000..d4ac52c --- /dev/null +++ b/app/Http/Requests/FileUpdateRequest.php @@ -0,0 +1,34 @@ + + */ + public function rules() + { + return [ + "alts" => [app()->collection->alt_required ? "required" : "nullable", 'array'], + "alts.*" => [app()->collection->alt_required ? "required" : "nullable", 'max:1000'], + "description" => [app()->collection->description_required ? "required" : "nullable", 'max:300'], + 'original_name' => ["string", "nullable", 'max:300'], + 'published_at' => ['date_format:Y-m-d H:i:s', 'nullable'], + ]; + } +} diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 28dec01..6689fb3 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -2,6 +2,7 @@ namespace App\Providers; +use App\Models\File; use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider; use Illuminate\Http\Request; diff --git a/routes/api.php b/routes/api.php index c0525d6..b6df73b 100644 --- a/routes/api.php +++ b/routes/api.php @@ -34,4 +34,6 @@ Route::group(['as' => 'api.'], function () { Route::get('{collection_name}/{uuid}.{extention}', [FileController::class, 'show'])->name('files.show'); // Route::get('{collection_name}/{path}', [FileController::class, 'private'])->name('files.private'); Route::post('{collection_name}/{model_id?}', [FileController::class, 'store'])->name('files.store'); + Route::put('{collection_name}/{uuid}.{extention}',[FileController::class,'update'])->name('files.update'); + Route::delete('{collection_name}/{uuid}.{extention}',[FileController::class,'destroy'])->withTrashed()->name('files.destroy'); }); diff --git a/tests/Feature/FileUpdateTest.php b/tests/Feature/FileUpdateTest.php index 6ddc664..1f96d41 100644 --- a/tests/Feature/FileUpdateTest.php +++ b/tests/Feature/FileUpdateTest.php @@ -2,20 +2,81 @@ namespace Tests\Feature; +use App\Image\ImageProcessor; +use App\Models\Collection; +use App\Models\File; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\WithFaker; +use Illuminate\Support\Facades\Storage; +use Tests\Feature\Traits\FileTraits; use Tests\TestCase; class FileUpdateTest extends TestCase { - /** - * A basic feature test example. - * - * @return void - */ - public function test_example() + use FileTraits; + public function test_user_can_not_access_update_without_permission() { - $this->assertTrue(true); + $this->assertFalse("it's not mohammad's fault, I'm waiting for dynamic policy"); + } + + public function test_user_update_not_exits_files_not_found() + { + $data = [ + "original_name" => 'original name is very bad', + "description" => 'this is a description for file and has beed updated', + ]; + + $response = $this->loginAs()->putJson(route('api.files.update', ['collection_name' => 'not_exits', 'uuid' => app()->uuid, 'extention' => 'jpg']), $data); + $response->assertNotFound(); + } + + + // /** + // * @dataProvider updateValidationTestProvider + // */ + // public function test_user_send_unproccable_fileds($collectionFields, $dataFields) + // { + // $collection = Collection::factory()->create($collectionFields); + // $uuid = app()->uuid; + // $file = File::factory()->createQuietly([ + // 'uuid' => $uuid, + // 'server_path' => '/' . date('y') . '/' . date('m') . '/', + // 'user_id' => auth()->id(), + // 'collection_id' => $collection->id + // ]); + + // $response = $this->loginAs()->postJson(route('api.files.update', ['collection_name' => $collection->name, 'uuid' => $file->uuid, 'ext' => $collection->ext]), $dataFields); + // $response->assertUnprocessable(); + // } + + public function test_user_can_update_file() + { + $collection = Collection::factory()->createQuietly([ + 'alt_required' => false, + 'description_required' => false, + 'tmp_support' => true, + 'max_width' => 2000, + 'max_height' => 2000, + 'min_width' => 1, + 'min_height' => 1, + 'min_file_size' => 0 + ]); + $uuid = app()->uuid; + $file = File::factory()->createQuietly([ + 'uuid' => $uuid, + 'server_path' => '/' . date('y') . '/' . date('m') . '/', + 'user_id' => auth()->id(), + 'collection_id' => $collection->id + ]); + $imageProcessor = new ImageProcessor; + $imageProcessor->createFakeImage(storage_path('stub') . '/image.png', Storage::disk($collection->disk)->path($file->server_path . $uuid . '.' . $collection->ext)); + + $data = [ + "original_name" => 'original name is very bad', + "description" => 'this is a description for file and has beed updated', + ]; + $response = $this->loginAs()->putJson(route('api.files.update', ['collection_name' => $collection->name, 'uuid' => $file->uuid, 'extention' => $collection->ext]), $data); + $response->assertok()->assertJson(['data' => $data]); } } diff --git a/tests/Feature/Traits/FileTraits.php b/tests/Feature/Traits/FileTraits.php index d9b9781..9d88668 100644 --- a/tests/Feature/Traits/FileTraits.php +++ b/tests/Feature/Traits/FileTraits.php @@ -27,6 +27,22 @@ trait FileTraits ]; } + private function defaultArrayForUpdate() + { + return [ + [ + 'alt_required' => false, + 'description_required' => false, + 'tmp_support' => true, + 'max_width' => 2000, + 'max_height' => 2000, + 'min_width' => 1, + 'min_height' => 1, + 'min_file_size' => 0 + ] + ]; + } + private function changeDefaultArrayAndReturn($defaultArray, $key, $value): array { $defaultArray[$key[0]][$key[1]] = $value; @@ -60,4 +76,14 @@ trait FileTraits ]; return $data; } + + public function updateValidationTestProvider() + { + + $data = [ + $this->changeDefaultArrayAndReturn($this->defaultArrayForUpdate(), [0, 'alt_required'], true), + $this->changeDefaultArrayAndReturn($this->defaultArrayForUpdate(), [0, 'description_required'], true), + ]; + return $data; + } }