Ver código fonte

Fix user-supplied file uploads registering as invalid

shalvah 4 anos atrás
pai
commit
5c7e0c89df

+ 1 - 1
config/scribe.php

@@ -108,7 +108,7 @@ return [
 
                     /*
                      * Files which should be sent with the API call.
-                     * Each value should be a valid path (absolute or relative to your project directory) to a file on this machine.
+                     * Each value should be a valid path (absolute or relative to your project directory) to a file on this machine (but not in the project root).
                      */
                     'fileParams' => [
                         // 'key' => 'storage/app/image.png',

+ 1 - 1
docs/documenting/documenting-endpoint-body-parameters.md

@@ -161,7 +161,7 @@ This gives:
 ## Documenting file uploads
 You can document file inputs by using `@bodyParam` or FormRequest rules with a type `file`. You can add a description and example as usual. 
 
-For files, your example should be the path to a file that exists on your machine. This path should be absolute or relative to your project directory. If you don't specify an example, Scribe will generate a fake file for example requests and response calls.
+For files, your example should be the path to a file that exists on your machine. This path should be absolute or relative to your project directory (but not in the project root). If you don't specify an example, Scribe will generate a fake file for example requests and response calls.
 
 ```php
 /**

+ 2 - 4
src/Extracting/Generator.php

@@ -3,13 +3,13 @@
 namespace Knuckles\Scribe\Extracting;
 
 use Faker\Factory;
+use Illuminate\Http\Testing\File;
 use Illuminate\Http\UploadedFile;
 use Illuminate\Routing\Route;
 use Illuminate\Support\Arr;
 use Illuminate\Support\Str;
 use Knuckles\Scribe\Extracting\Strategies\Strategy;
 use Knuckles\Scribe\Tools\DocumentationConfig;
-use Knuckles\Scribe\Tools\ConsoleOutputUtils as c;
 use Knuckles\Scribe\Tools\Utils as u;
 use ReflectionClass;
 use ReflectionFunctionAbstract;
@@ -390,9 +390,7 @@ class Generator
     protected static function convertStringValueToUploadedFileInstance(string $filePath): UploadedFile
     {
         $fileName = basename($filePath);
-        return new UploadedFile(
-            $filePath, $fileName, mime_content_type($filePath), 0, false
-        );
+        return new File($fileName, fopen($filePath, 'r'));
     }
 
     /**

+ 1 - 0
src/Extracting/Strategies/Responses/ResponseCalls.php

@@ -129,6 +129,7 @@ class ResponseCalls extends Strategy
         // The second is so they get added to the request bag
         // (where Symfony usually reads from and Laravel sometimes does)
         // Adding to both ensures consistency
+
         $request = Request::create($uri, $method, [], $cookies, $fileParameters, $this->transformHeadersToServerVars($headers), json_encode($bodyParams));
         // Doing it again to catch any ones we didn't transform properly.
         $request = $this->addHeaders($request, $route, $headers);

+ 9 - 2
tests/Fixtures/TestController.php

@@ -4,6 +4,7 @@ namespace Knuckles\Scribe\Tests\Fixtures;
 
 use Illuminate\Http\Request;
 use Illuminate\Routing\Controller;
+use Illuminate\Validation\ValidationException;
 use Knuckles\Scribe\Tests\Unit\GeneratorTest;
 use Knuckles\Scribe\Tools\Utils;
 
@@ -95,11 +96,17 @@ class TestController extends Controller
      * Endpoint with body form data parameters.
      *
      * @bodyParam name string required Name of image. Example: cat.jpg
-     * @bodyParam image file required The image.
+     * @bodyParam image file required The image. Example: config/scribe.php
      */
     public function withFormDataParams()
     {
-        return '';
+        dump(request()->file('image')->isValid());
+        request()->validate(['image' => 'file|required']);
+        return [
+            'filename' => request()->file('image')->getFilename(),
+            'filepath' => request()->file('image')->getPath(),
+            'name' => request('name'),
+        ];
     }
 
     /**

+ 22 - 4
tests/Strategies/Responses/ResponseCallsTest.php

@@ -4,6 +4,8 @@ namespace Knuckles\Scribe\Tests\Strategies\Responses;
 
 use Dingo\Api\Routing\Router;
 use Illuminate\Routing\Route;
+use Illuminate\Support\Facades\Route as RouteFacade;
+use Knuckles\Scribe\Extracting\Generator;
 use Knuckles\Scribe\Extracting\Strategies\Responses\ResponseCalls;
 use Knuckles\Scribe\ScribeServiceProvider;
 use Knuckles\Scribe\Tests\Fixtures\TestController;
@@ -55,6 +57,22 @@ class ResponseCallsTest extends TestCase
         ], json_decode($results[0]['content'], true));
     }
 
+    /** @test */
+    public function can_upload_file_parameters_in_response_calls()
+    {
+        $route = RouteFacade::post('/withFormDataParams', [TestController::class, 'withFormDataParams']);
+
+        config(['scribe.routes.0.apply.response_calls.methods' => ['POST']]);
+        $parsed = (new Generator())->processRoute($route, config('scribe.routes.0.apply'));
+
+        $this->assertEquals([
+            [
+                "status" => 200,
+                "content" => '{"filename":"scribe.php","filepath":"config","name":"cat.jpg"}',
+            ],
+        ], $parsed['responses']);
+    }
+
     /** @test */
     public function uses_configured_settings_when_calling_route()
     {
@@ -160,7 +178,7 @@ class ResponseCallsTest extends TestCase
      */
     public function uses_configured_settings_when_calling_route_with_dingo()
     {
-        $route = $this->registerDingoRoute('post','/echo/{id}', 'shouldFetchRouteResponseWithEchoedSettings');
+        $route = $this->registerDingoRoute('post', '/echo/{id}', 'shouldFetchRouteResponseWithEchoedSettings');
 
         $rules = [
             'response_calls' => [
@@ -198,7 +216,7 @@ class ResponseCallsTest extends TestCase
      */
     public function can_override_application_config_during_response_call_with_dingo()
     {
-        $route = $this->registerDingoRoute('post','/echoesConfig', 'echoesConfig');
+        $route = $this->registerDingoRoute('post', '/echoesConfig', 'echoesConfig');
 
         $rules = [
             'response_calls' => [
@@ -245,8 +263,8 @@ class ResponseCallsTest extends TestCase
                 [
                     'status' => 200,
                     'content' => json_encode(['message' => 'LOL']),
-                ]
-            ]
+                ],
+            ],
         ];
         $strategy = new ResponseCalls(new DocumentationConfig([]));
         $results = $strategy->makeResponseCallIfEnabledAndNoSuccessResponses($route, $rules, $context);