diff --git a/Dockerfile b/Dockerfile index 311052a..b7547b6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,4 +9,5 @@ RUN apt-get -y update \ && apt-get -y install libvips-tools \ && apt-get -y install libvips-dev \ && pecl install vips \ - && echo 'extension="vips.so"' > /usr/local/etc/php/conf.d/20-vips.ini + && echo 'extension="vips.so"' > /usr/local/etc/php/conf.d/20-vips.ini \ + && echo "ffi.enable=true" >> /usr/local/etc/php/php.ini diff --git a/app/Http/Controllers/FileController.php b/app/Http/Controllers/FileController.php index 919db7a..4a5e417 100644 --- a/app/Http/Controllers/FileController.php +++ b/app/Http/Controllers/FileController.php @@ -13,6 +13,8 @@ use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Validator; use Symfony\Component\Console\Input\Input; +use function PHPUnit\Framework\isNull; + class FileController extends Controller { public function show($collection, $uuid, $ext) @@ -22,68 +24,17 @@ class FileController extends Controller public function private($collection, $path) { - // Storage::disk(app()->collection->disk)->download($path); + Storage::disk('local')->download($path); } - public function store(Request $request, ImageProcessor $imageProcessor) + public function store(FileStoreRequest $request, ImageProcessor $imageProcessor) { - - if (!app()->collection->tmp_support && !$request->model_id) { - return abort(403); - } - - if (app()->collection->count !== 1 && (app()->collection->count <= File::where('model_id', auth()->id())->count()) && !app()->collection->tmp_support) { - return abort(403); - } - - if (!isset(app()->file) && is_null($request->file('file'))) { - return abort(403); - } - - $fieldsValidate = [ - "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'], - 'public' => ['boolean', 'nullable'], - 'published_at' => ['date_format:Y-m-d H:i:s', 'nullable'], - ]; - - $fieldsValidate['file'] = - is_null($request->file('file')) ? - [ - 'string', - 'required', - 'max:300' - ] : - [ - "mimes:" . app()->collection->getExts(), - "mimetypes:" . app()->collection->getMimeTypes(), - !$this->isImage($request->file->path()) ?: "dimensions:min_width=" . app()->collection->min_width . ",min_height=" . app()->collection->min_height . ',max_width=' . app()->collection->max_width . ',max_height=' . app()->collection->max_height, - "max:" . app()->collection->max_file_size, - "min:" . app()->collection->min_file_size, - ]; - - $validated = $request->validate($fieldsValidate); - - if (is_null($request->file('file'))) { - $storedImage = new \Illuminate\Http\File(Storage::disk('local')->path(app()->file->server_path)); - $validated = Validator::make(['file' => $storedImage], ["file" => [ - "mimes:" . app()->collection->getExts(), - "mimetypes:" . app()->collection->getMimeTypes(), - "dimensions:min_width=" . app()->collection->min_width . ",min_height=" . app()->collection->min_height . ',max_width=' . app()->collection->max_width . ',max_height=' . app()->collection->max_height, - "max:" . app()->collection->max_file_size, - "min:" . app()->collection->min_file_size - ]])->validate(); - } - + $request->file = $imageProcessor->convertImage($request->file->path(),'/tmp/' . app()->uuid . '.' . app()->collection->ext); if (!is_null(app()->collection->process)) { - $imageProcessor->process($request->file->path(), $request->file->path(), app()->collection->process); + $request->file = $imageProcessor->process($request->file->path(),'/tmp/' . app()->uuid. '.' . app()->collection->ext, app()->collection->process); } - DB::transaction(function () use ($request) { - $uuid = app()->uuid; $request->resourceFile = File::create([ 'uuid' => $uuid, @@ -101,22 +52,20 @@ class FileController extends Controller 'ip' => $request->ip(), 'collection_id' => app()->collection->id, 'published_at' => $request->published_at, - 'server_path' => '/' . date('y') . '/' . date('m') . '/' . $uuid . '.' . app()->collection->ext, + 'server_path' => '/' . date('y') . '/' . date('m') . '/', ]); - if (!app()->collection->tmp_support && app()->collection->count == 1) { File::where('user_id', auth()->id())->delete(); } - $storedImage = $request->file->storeAs($request->resourceFile->server_path, app()->uuid . '.' . app()->collection->ext, app()->collection->disk); + $storedFile = Storage::disk(app()->collection->disk)->putFileAs('', $request->file,$request->resourceFile->server_path . $request->resourceFile->uuid . '.' . app()->collection->ext); if (app()->collection->public) { - Storage::setVisibility($storedImage, 'public'); + Storage::disk(app()->collection->disk)->setVisibility($storedFile, 'public'); } }); return new FileResource($request->resourceFile); } - public function update(Request $request, $id) { // diff --git a/app/Http/Controllers/Traits/FileTrait.php b/app/Http/Controllers/Traits/FileTrait.php index 097bb69..a413431 100644 --- a/app/Http/Controllers/Traits/FileTrait.php +++ b/app/Http/Controllers/Traits/FileTrait.php @@ -4,12 +4,5 @@ namespace App\Http\Controllers\Traits; trait FileTrait { - public function isImage($file) - { - if(@is_array(getimagesize($file))){ - return true; - } else { - return false; - } - } + } diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 9217b71..35fb8b0 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -45,7 +45,7 @@ class Kernel extends HttpKernel // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class, - BindModelDocumentMiddleware::class, + // BindModelDocumentMiddleware::class, BindCollectionModelMiddleware::class, BindFileModelMiddleware::class, ], diff --git a/app/Http/Middleware/BindCollectionModelMiddleware.php b/app/Http/Middleware/BindCollectionModelMiddleware.php index ddabc53..f984c8c 100644 --- a/app/Http/Middleware/BindCollectionModelMiddleware.php +++ b/app/Http/Middleware/BindCollectionModelMiddleware.php @@ -18,15 +18,15 @@ class BindCollectionModelMiddleware */ public function handle(Request $request, Closure $next) { - if ($request->route()->action['as'] == 'api.file.store') { + if ($request->route()->action['as'] == 'api.files.store') { app()->singleton('collection', function () use ($request) { - return Collection::where('name', $request->route('collection_name'))->get()->first(); + return Collection::where('name', $request->route('collection_name'))->firstOrFail(); }); } if ($request->route()->action['as'] == 'api.file.private') { app()->singleton('collection', function () use ($request) { - return Collection::where('name', $request->route('collection_name'))->get()->first(); + return Collection::where('name', $request->route('collection_name'))->firstOrFail(); }); } diff --git a/app/Http/Middleware/BindFileModelMiddleware.php b/app/Http/Middleware/BindFileModelMiddleware.php index e1289be..8bfad45 100644 --- a/app/Http/Middleware/BindFileModelMiddleware.php +++ b/app/Http/Middleware/BindFileModelMiddleware.php @@ -2,10 +2,12 @@ namespace App\Http\Middleware; +use App\Models\Collection; use App\Models\File; use Closure; use Illuminate\Support\Str; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Storage; class BindFileModelMiddleware { @@ -18,11 +20,15 @@ class BindFileModelMiddleware */ public function handle(Request $request, Closure $next) { - if ($request->route()->action['as'] == 'api.file.store') { - if(is_null($request->file('file'))){ - app()->bind('file', function () use ($request) { - return File::find($request->file); - }); + if (($request->route()->action['as'] == 'api.files.store') && is_null($request->file('file'))) { + $file = File::find($request->file); + if (!is_null($file)) { + $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; + }); + } } } diff --git a/app/Http/Requests/FileStoreRequest.php b/app/Http/Requests/FileStoreRequest.php new file mode 100644 index 0000000..45b602d --- /dev/null +++ b/app/Http/Requests/FileStoreRequest.php @@ -0,0 +1,73 @@ +collection->tmp_support && !$this->model_id) { + return false; + } + + if (app()->collection->count !== 1 && (app()->collection->count <= File::where('model_id', auth()->id())->count()) && !app()->collection->tmp_support) { + + return false; + } + if (!app()->bound('file') && is_null($this->file('file'))) { + return false; + } + + if (!$this->hasFile('file')) { + $this->replace([ + 'file' => new \Illuminate\Http\File(Storage::disk(app()->collection->disk)->path(app()->file->server_path . app()->file->uuid . '.' . app()->collection->ext), app()->file->uuid . '.' . app()->collection->ext) + ]); + } + + return true; + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + "file" => [ + "mimes:" . app()->collection->getExts(), + "mimetypes:" . app()->collection->getMimeTypes(), + !$this->isImage(request()->file->path()) ?: "dimensions:min_width=" . app()->collection->min_width . ",min_height=" . app()->collection->min_height . ',max_width=' . app()->collection->max_width . ',max_height=' . app()->collection->max_height, + "max:" . app()->collection->max_file_size, + "min:" . app()->collection->min_file_size, + ], + "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'], + 'public' => ['boolean', 'nullable'], + 'published_at' => ['date_format:Y-m-d H:i:s', 'nullable'], + ]; + } +} diff --git a/app/Image/ImageProcessor.php b/app/Image/ImageProcessor.php index bc61664..954655c 100644 --- a/app/Image/ImageProcessor.php +++ b/app/Image/ImageProcessor.php @@ -7,32 +7,10 @@ use Jcupitt\Vips\Interpretation; class ImageProcessor { - public function brightness($image, float $brightness = 1.0, float $saturation = 1.0, float $hue = 0.0) - { - $oldInterpretation = $image->interpretation; - $hue %= 360; - if ($hue < 0) { - $hue = 360 + $hue; - } - if ($image->hasAlpha()) { - $imageWithoutAlpha = $image->extract_band(0, ['n' => $image->bands - 1]); - $alpha = $image->extract_band($image->bands - 1, ['n' => 1]); - return $imageWithoutAlpha - ->colourspace(Interpretation::LCH) - ->linear([$brightness, $saturation, 1.0], [0.0, 0.0, $hue]) - ->colourspace($oldInterpretation) - ->bandjoin($alpha); - } - return $image - ->colourspace(Interpretation::LCH) - ->linear([$brightness, $saturation, 1.0], [0.0, 0.0, $hue]) - ->colourspace($oldInterpretation); - } - public function process(string $filename, string $target, array $options = ["w" => null, "h" => null, "r" => null,"flip" => null , "canv" => null,"rotation" => null],$saveOptions = ['Q' => 100]) { if (!isset($options['w']) && !isset($options['h'])) { - $image = Image::thumbnail($filename, getimagesize($filename)[0]); + $image = Image::thumbnail($filename, getimagesize($filename)[1]); } if (isset($options['r'])) { @@ -105,6 +83,41 @@ class ImageProcessor $image->writeToFile($target,$saveOptions); - return $target; + return new \Illuminate\Http\File($target); + } + + public function createFakeImage($stub,$path, $saveOptions = ['Q' => 100],$options = ["w" => null, "h" => null, "r" => null,"flip" => null , "canv" => null,"rotation" => null]) + { + $image = $this->process($stub,$path,$options,$saveOptions); + } + + + public function brightness($image, float $brightness = 1.0, float $saturation = 1.0, float $hue = 0.0) + { + $oldInterpretation = $image->interpretation; + $hue %= 360; + if ($hue < 0) { + $hue = 360 + $hue; + } + if ($image->hasAlpha()) { + $imageWithoutAlpha = $image->extract_band(0, ['n' => $image->bands - 1]); + $alpha = $image->extract_band($image->bands - 1, ['n' => 1]); + return $imageWithoutAlpha + ->colourspace(Interpretation::LCH) + ->linear([$brightness, $saturation, 1.0], [0.0, 0.0, $hue]) + ->colourspace($oldInterpretation) + ->bandjoin($alpha); + } + return $image + ->colourspace(Interpretation::LCH) + ->linear([$brightness, $saturation, 1.0], [0.0, 0.0, $hue]) + ->colourspace($oldInterpretation); + } + + public function convertImage(string $filePath,string $target,array $options = ['Q' => 100]) : \Illuminate\Http\File + { + $tmpFile = \Jcupitt\Vips\Image::newFromFile($filePath); + $tmpFile->writeToFile($target,$options); + return new \Illuminate\Http\File($target); } } diff --git a/app/Models/File.php b/app/Models/File.php index 69650ed..eb555d7 100644 --- a/app/Models/File.php +++ b/app/Models/File.php @@ -3,6 +3,7 @@ namespace App\Models; use App\Models\Traits\Validatable; +use App\Models\Traits\ValidationMaker; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; @@ -15,6 +16,8 @@ class File extends Model protected $primaryKey = 'uuid'; + public $incrementing = false; + protected $fillable = [ "uuid", "original_name", @@ -46,16 +49,5 @@ class File extends Model ); } - // public function rules(): array - // { - // return [ - // "image" => [ - // "mimes:" . app()->collection->getExts(), - // "mimetypes:" . app()->collection->getMimeTypes(), - // "dimensions:min_width=" . app()->collection->min_width . ",min_height=" . app()->collection->min_height . ',max_width=' . app()->collection->max_width . ',max_height=' . app()->collection->max_height, - // "max:" . app()->collection->max_size, - // "min:" . app()->collection->min_size, - // ], - // ]; - // } + } diff --git a/app/Models/Traits/Validatable.php b/app/Models/Traits/Validatable.php index ddf6915..ca2e336 100644 --- a/app/Models/Traits/Validatable.php +++ b/app/Models/Traits/Validatable.php @@ -59,7 +59,9 @@ trait Validatable $rules = array_merge($rules, $this->createValidations()); $rules = array_merge($rules, $this->createValidations('category_data')); + $validator = Validator::make($this->toArray(), $rules); + if ($abort && $validator->fails()) { throw new ValidationException($validator, new JsonResponse([ @@ -83,7 +85,6 @@ trait Validatable return $abort ? $this : true; } - public function getLoads() { return []; diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 34c5d64..6f766d5 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -27,7 +27,7 @@ class AppServiceProvider extends ServiceProvider { Storage::disk('local')->buildTemporaryUrlsUsing(function ($path, $expiration, $options) { return URL::temporarySignedRoute( - 'api.file.private', + 'api.files.private', $expiration, array_merge($options, ['path' => $path]) ); diff --git a/config/filesystems.php b/config/filesystems.php index 1b24a72..374f1ca 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -48,6 +48,14 @@ return [ ], ], + 'tmp' => [ + 'driver' => 'local', + 'root' => '/tmp', + 'url' => env('APP_URL') . '/storage', + 'visibility' => 'public', + 'throw' => false, + ], + // 'public' => [ // 'driver' => 'local', // 'root' => storage_path('app/public'), diff --git a/database/factories/BaseFactory.php b/database/factories/BaseFactory.php index 912ed3c..36b663d 100644 --- a/database/factories/BaseFactory.php +++ b/database/factories/BaseFactory.php @@ -69,16 +69,4 @@ trait BaseFactory }); } - - public function withImage() - { - return null; - } - - public function createImage($path, $saveOptions = ['Q' => 100],$options = ["w" => null, "h" => null, "r" => null,"flip" => null , "canv" => null,"rotation" => null]) - { - $imageProcessor = new ImageProcessor; - $image = $imageProcessor->process(storage_path('stub') . '/image.png',$path,$options,$saveOptions); - return $this; - } } diff --git a/database/factories/Documents/PolicyDocumentFactory.php b/database/factories/Documents/PolicyDocumentFactory.php index 2446684..238b797 100755 --- a/database/factories/Documents/PolicyDocumentFactory.php +++ b/database/factories/Documents/PolicyDocumentFactory.php @@ -4,10 +4,14 @@ namespace Database\Factories\Documents; use App\Documents\ModelDocument; use App\Documents\PolicyDocument; +use Database\Factories\BaseFactory; use Illuminate\Database\Eloquent\Factories\Factory; class PolicyDocumentFactory extends Factory + { + use BaseFactory; + protected $model = PolicyDocument::class; public function definition() @@ -19,4 +23,9 @@ class PolicyDocumentFactory extends Factory 'needs' => [], ]; } + + public function dependencyProvider() + { + return []; + } } diff --git a/database/factories/FileFactory.php b/database/factories/FileFactory.php index 5949c0a..344efe0 100644 --- a/database/factories/FileFactory.php +++ b/database/factories/FileFactory.php @@ -29,6 +29,7 @@ class FileFactory extends Factory "height" => rand(300, 2000), "file_size" => rand(300, 2000), "sort" => rand(0, 23), + "server_path" => '/' . date('y') . '/' . date('m') . '/', "alts" => [ 'hello wroldswdfouiwref iuwrhgf ow rgfaw ghfawej', 'jhsf asduyfsadf sadf safsuf isfjsdfsudifsduiyf sdiuf sd' diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index a406d7e..6e89110 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -2,8 +2,12 @@ namespace Database\Seeders; +use App\Image\ImageProcessor; +use App\Models\Collection; +use App\Models\File; use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; +use Illuminate\Support\Facades\Storage; class DatabaseSeeder extends Seeder { @@ -21,28 +25,49 @@ class DatabaseSeeder extends Seeder // 'email' => 'test@example.com', // ]); - \App\Models\Collection::factory()->create([ - "name" => "fuck", - "count" => 1, - "tmp_support" => 0, - "remove_tmp_time" => 132, - "max_file_size" => 100000000, - "min_file_size" => 10, - "max_width" =>2000, - "min_width" =>10, - "max_height" => 2000, - "min_height" =>10, - "alt_required" => 0, - "description_required" =>0, - "exts" => [ - "jpg", - "jpeg", - "png", - "webp" - ], - "ext" => "webp", + // \App\Models\Collection::factory()->create([ + // "name" => "fuck", + // "count" => 1, + // "tmp_support" => 0, + // "remove_tmp_time" => 132, + // "max_file_size" => 100000000, + // "min_file_size" => 10, + // "max_width" =>2000, + // "min_width" =>10, + // "max_height" => 2000, + // "min_height" =>10, + // "alt_required" => 0, + // "description_required" =>0, + // "exts" => [ + // "jpg", + // "jpeg", + // "png", + // "webp" + // ], + // "ext" => "webp", + // ]); + // \App\Models\Collection::factory(10)->create(); + // \App\Models\File::factory()->create(); + $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, + 'public' => false + ]); + $uuid = app()->uuid; + $file = File::factory()->createQuietly([ + 'uuid' => $uuid, + 'server_path' => '/' . date('y') . '/' . date('m') . '/', + 'user_id' => auth()->id(), + 'collection_id' => $collection->id ]); - \App\Models\Collection::factory(10)->create(); - \App\Models\File::factory()->create(); + $imageProcessor = new ImageProcessor; + $imageProcessor->createFakeImage(storage_path('stub') . '/image.png', Storage::disk($collection->disk)->path($file->server_path . $uuid . '.' . $collection->ext)); + } } diff --git a/public/image-modified.webp b/public/image-modified.webp deleted file mode 100644 index a3d801f..0000000 Binary files a/public/image-modified.webp and /dev/null differ diff --git a/routes/api.php b/routes/api.php index 62cc75d..3c462a3 100644 --- a/routes/api.php +++ b/routes/api.php @@ -2,7 +2,10 @@ use App\Http\Controllers\CollectionController; use App\Http\Controllers\FileController; +use App\Models\File; +use Illuminate\Http\UploadedFile; use Illuminate\Support\Facades\Route; +use Illuminate\Support\Facades\Storage; /* |-------------------------------------------------------------------------- @@ -19,10 +22,16 @@ use Illuminate\Support\Facades\Route; // return $request->user(); // }); +Route::get('newTmp/{uuid}', function ($uuid) { + $file = File::find($uuid); + return Storage::disk('local')->temporaryUrl($file->server_path . $file->uuid . '.webp', now()->addMinutes(5),['collection_name'=>'Paris Renner II']); +})->name('newTmp'); + + Route::group(['as' => 'api.'], function () { Route::apiResource('collections', CollectionController::class); Route::delete('collections/{collection}', [CollectionController::class, "destroy"])->withTrashed(); - Route::get('{collection_name}/{uuid}.{extention}', [FileController::class, 'show'])->name('file.show'); - Route::get('{collection_name}/{path}', [FileController::class, 'private'])->name('file.private'); - Route::post('{collection_name}/{model_id?}', [FileController::class, 'store'])->name('file.store'); + // 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'); }); diff --git a/routes/web.php b/routes/web.php index 0958771..e4a55a9 100644 --- a/routes/web.php +++ b/routes/web.php @@ -21,17 +21,14 @@ use Jcupitt\Vips\Utils; | contains the "web" middleware group. Now create something great! | */ -Route::get('/fuck.webp',function(Request $request,ImageProcessor $imageProcessor) +Route::get('/fuck',function(Request $request,ImageProcessor $imageProcessor) { - $option = [ - 'w' => $request->w, - 'h' => $request->h, - 'r' => $request->r, - 'canv' => $request->canv, - ]; - $imageProcessor->process(public_path('image.png'),public_path('image-modified.webp'),$option); - - return response()->file(public_path('image-modified.webp')); + $image = Image::thumbnail(storage_path('stub') . '/image.png', getimagesize(storage_path('stub') . '/image.png')[1]); + $image->writeToFile(public_path(). '/fuck.jpg',['Q'=> 100]); + // $imageProcessor->process(public_path('image.png'),public_path('image-modified.webp')); + + // return response()->file(storage_path('stub') . '/image.png'); + return response()->file(public_path(). '/fuck.jpg'); }); Route::get('/', function (Request $request) { diff --git a/storage/image-modified.webp b/storage/image-modified.webp deleted file mode 100644 index fa30048..0000000 Binary files a/storage/image-modified.webp and /dev/null differ diff --git a/tests/Feature/FileStoreTest.php b/tests/Feature/FileStoreTest.php index 40f826f..3083266 100644 --- a/tests/Feature/FileStoreTest.php +++ b/tests/Feature/FileStoreTest.php @@ -3,11 +3,13 @@ namespace Tests\Feature; use App\Http\Controllers\Traits\FileTrait; +use App\Image\ImageProcessor; use App\Models\Collection; use App\Models\File; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\WithFaker; use Illuminate\Http\UploadedFile; +use Illuminate\Support\Facades\Storage; use Tests\Bootstrap; use Tests\TestCase; use Illuminate\Support\Str; @@ -28,8 +30,8 @@ class FileStoreTest extends Bootstrap $collection = Collection::factory()->create([ 'tmp_support' => false ]); - $response = $this->loginAs('dick')->postJson(route('api.file.store', ['collection_name' => $collection->name]), $data); + $response = $this->postJson(route('api.files.store', ['collection_name' => $collection->name]), $data); $response->assertForbidden(); } @@ -40,7 +42,7 @@ class FileStoreTest extends Bootstrap 'tmp_support' => false, 'count' => $randomCount ]); - for($i=$randomCount; $i > 0; $i--) { + for ($i = $randomCount; $i > 0; $i--) { $uuid = app()->uuid; $this->one(File::class, [ 'uuid' => $uuid, @@ -56,17 +58,15 @@ class FileStoreTest extends Bootstrap "description" => 'lfjdsklfslfsdlfasdfsfhgsfgsdf', "public" => 1 ]; - $response = $this->loginAs('dick')->postJson(route('api.file.store', ['collection_name' => $collection->name]), $data); + $response = $this->postJson(route('api.files.store', ['collection_name' => $collection->name]), $data); $response->assertForbidden(); } public function test_file_is_not_isset_forbidden() { - $collection = Collection::factory()->create([ 'tmp_support' => true ]); - $data = [ "file" => app()->uuid, "alts" => ['1', '2', '3'], @@ -74,11 +74,29 @@ class FileStoreTest extends Bootstrap "public" => 1 ]; - $response = $this->loginAs('dick')->postJson(route('api.file.store', ['collection_name' => $collection->name]), $data); - + $response = $this->postJson(route('api.files.store', ['collection_name' => $collection->name]), $data); $response->assertForbidden(); } + public function test_user_can_not_access_not_ownered_files() + { + $collection = Collection::factory()->createQuietly(); + $uuid = app()->uuid; + $file = File::factory()->createQuietly([ + 'uuid' => $uuid, + 'user_id' => auth()->id() + 1234, + 'server_path' => '/' . date('y') . '/' . date('m') . '/', + 'collection_id' => $collection->id + ]); + + $data = [ + "file" => $file->uuid, + "public" => 1 + ]; + + $response = $this->postJson(route('api.files.store', ['collection_name' => $collection->name]), $data); + $response->assertForbidden(); + } /** * @dataProvider storeValidationTestProvider @@ -86,7 +104,7 @@ class FileStoreTest extends Bootstrap public function test_store_dynamic_validation_unprocessable($collectionFields, $dataFields) { $collection = Collection::factory()->create($collectionFields); - $response = $this->loginAs('dick')->postJson(route('api.file.store', ['collection_name' => $collection->name]), $dataFields); + $response = $this->postJson(route('api.files.store', ['collection_name' => $collection->name]), $dataFields); $response->assertUnprocessable(); } @@ -104,10 +122,34 @@ class FileStoreTest extends Bootstrap // } - public function test_store_dynamic_validation_stored_file_unprocessable() + /** + * @dataProvider storeValidationTestProvider + */ + public function test_store_dynamic_validation_stored_file_unprocessable($collectionFields) { + $collection = Collection::factory()->createQuietly($collectionFields); + $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)); - $collection = Collection::factory()->create([ + $data = [ + "file" => $file->uuid, + "public" => 1 + ]; + + $response = $this->postJson(route('api.files.store', ['collection_name' => $collection->name]), $data); + $response->assertUnprocessable(); + } + + public function test_user_can_store_sent_file_count_multiple_without_image_processor_ok() + { + $collection = Collection::factory()->createQuietly([ 'alt_required' => false, 'description_required' => false, 'tmp_support' => true, @@ -118,21 +160,112 @@ class FileStoreTest extends Bootstrap 'min_file_size' => 0 ]); $uuid = app()->uuid; - $file = File::factory()->createImage(storage_path('app/' . date('y') . '/' . date('m') . '/' . $uuid . '.' . $collection->ext))->create([ + $this->one(File::class, [ 'uuid' => $uuid, + 'user_id' => auth()->id(), + 'collection_id' => $collection->id, 'server_path' => '/' . date('y') . '/' . date('m') . '/', + ]); + + $data = [ + "file" => UploadedFile::fake()->image('test.png'), + "public" => 1 + ]; + $response = $this->postJson(route('api.files.store', ['collection_name' => $collection->name]), $data); + $response->assertCreated(); + } + + public function test_user_can_store_sent_file_uuid_count_multiple_without_image_processor_ok() + { + $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 = [ "file" => $file->uuid, - "alts" => ['1', '2', '3'], - "description" => 'lfjdsklfslfsdlfasdfsfhgsfgsdf', "public" => 1 ]; - $response = $this->loginAs('dick')->postJson(route('api.file.store', ['collection_name' => $collection->name]), $data); + $response = $this->postJson(route('api.files.store', ['collection_name' => $collection->name]), $data); + $response->assertCreated(); + } - $response->assertUnprocessable(); + public function test_user_can_store_sent_file_count_one_without_image_processor_ok() + { + $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 = [ + "file" => $file->uuid, + "public" => 1 + ]; + + $response = $this->postJson(route('api.files.store', ['collection_name' => $collection->name]), $data); + $response->assertCreated(); } + + public function test_user_can_store_sent_file_uuid_count_one_without_image_processor_ok() + { + $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 = [ + "file" => $file->uuid, + "public" => 1 + ]; + + $response = $this->postJson(route('api.files.store', ['collection_name' => $collection->name]), $data); + $response->assertCreated(); + } + }