From aa16043f2d8a07fca559968e4aa30d5b546ac024 Mon Sep 17 00:00:00 2001 From: Gazder Bence Date: Thu, 8 Mar 2018 12:13:44 +0100 Subject: [PATCH 1/2] Add getMiddleware function to Route class (#1537) * Add getMiddleware function to Route class The getMiddleware function is missing and reported here: https://github.com/flipboxstudio/lumen-generator/issues/25 Also I think you have to be able to query the middlewares. If the function is not necessary and you can query the middlewares with another method, please write it in the comments. * Fix style * Fix style --- src/Routing/Route.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Routing/Route.php b/src/Routing/Route.php index 308b801..3a70032 100644 --- a/src/Routing/Route.php +++ b/src/Routing/Route.php @@ -533,4 +533,14 @@ public function secure() { return in_array('https', $this->action, true); } + + /** + * Return the middlewares for this route. + * + * @return array + */ + public function getMiddleware() + { + return $this->middleware; + } } From 14225351b2a9b652f6814851539370645c0c1fac Mon Sep 17 00:00:00 2001 From: Gazder Bence Date: Thu, 8 Mar 2018 12:16:44 +0100 Subject: [PATCH 2/2] Fix FormRequests missing class error (#1534) * Fix FormRequests missing class error * Fix styleCI * Fix Style ci * Fix style ci * Add missing use statements --- src/Http/FormRequest.php | 246 +++++++++++++++++++++++++- src/Provider/LumenServiceProvider.php | 51 ++++++ 2 files changed, 294 insertions(+), 3 deletions(-) diff --git a/src/Http/FormRequest.php b/src/Http/FormRequest.php index 646bf70..d4839c8 100644 --- a/src/Http/FormRequest.php +++ b/src/Http/FormRequest.php @@ -2,17 +2,145 @@ namespace Dingo\Api\Http; +use Illuminate\Http\Request; +use Illuminate\Http\JsonResponse; +use Laravel\Lumen\Http\Redirector; +use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Validation\Validator; use Dingo\Api\Exception\ValidationHttpException; +use Illuminate\Validation\ValidatesWhenResolvedTrait; use Symfony\Component\HttpKernel\Exception\HttpException; -use Illuminate\Foundation\Http\FormRequest as IlluminateFormRequest; +use Illuminate\Contracts\Validation\ValidatesWhenResolved; +use Illuminate\Contracts\Validation\Factory as ValidationFactory; +use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; -class FormRequest extends IlluminateFormRequest +class FormRequest extends Request implements ValidatesWhenResolved { + use ValidatesWhenResolvedTrait; + + /** + * The container instance. + * + * @var \Illuminate\Contracts\Container\Container + */ + protected $container; + + /** + * The redirector instance. + * + * @var \Illuminate\Routing\Redirector + */ + protected $redirector; + + /** + * The URI to redirect to if validation fails. + * + * @var string + */ + protected $redirect; + + /** + * The route to redirect to if validation fails. + * + * @var string + */ + protected $redirectRoute; + + /** + * The controller action to redirect to if validation fails. + * + * @var string + */ + protected $redirectAction; + + /** + * The key to be used for the view error bag. + * + * @var string + */ + protected $errorBag = 'default'; + + /** + * The input keys that should not be flashed on redirect. + * + * @var array + */ + protected $dontFlash = [ + 'password', + 'password_confirmation', + ]; + + /** + * Validate the request. + */ + public function validate() + { + if ($this->authorize() === false) { + throw new AccessDeniedHttpException(); + } + + $validator = app('validator')->make($this->all(), $this->rules(), $this->messages()); + + if ($validator->fails()) { + throw new ValidationHttpException($validator->errors()); + } + } + + /** + * Get the validator instance for the request. + * + * @return \Illuminate\Contracts\Validation\Validator + * + * @SuppressWarnings(PHPMD.ElseExpression) + */ + protected function getValidatorInstance() + { + $factory = $this->container->make(ValidationFactory::class); + + if (method_exists($this, 'validator')) { + $validator = $this->container->call([$this, 'validator'], compact('factory')); + } else { + $validator = $this->createDefaultValidator($factory); + } + + if (method_exists($this, 'withValidator')) { + $this->withValidator($validator); + } + + return $validator; + } + + /** + * Create the default validator instance. + * + * @param \Illuminate\Contracts\Validation\Factory $factory + * + * @return \Illuminate\Contracts\Validation\Validator + */ + protected function createDefaultValidator(ValidationFactory $factory) + { + return $factory->make( + $this->validationData(), + $this->container->call([$this, 'rules']), + $this->messages(), + $this->attributes() + ); + } + + /** + * Get data to be validated from the request. + * + * @return array + */ + protected function validationData() + { + return $this->all(); + } + /** * Handle a failed validation attempt. * - * @param \Illuminate\Contracts\Validation\Validator $validator + * @param \Illuminate\Contracts\Validation\Validator $validator * * @return void */ @@ -25,6 +153,70 @@ protected function failedValidation(Validator $validator) parent::failedValidation($validator); } + /** + * Get the proper failed validation response for the request. + * + * @param array $errors + * + * @return \Symfony\Component\HttpFoundation\Response + */ + public function response(array $errors) + { + if ($this->expectsJson()) { + return new JsonResponse($errors, 422); + } + + return $this->redirector->to($this->getRedirectUrl()) + ->withInput($this->except($this->dontFlash)) + ->withErrors($errors, $this->errorBag); + } + + /** + * Format the errors from the given Validator instance. + * + * @param \Illuminate\Contracts\Validation\Validator $validator + * + * @return array + */ + protected function formatErrors(Validator $validator) + { + return $validator->getMessageBag()->toArray(); + } + + /** + * Get the URL to redirect to on a validation error. + * + * @return string + */ + protected function getRedirectUrl() + { + $url = $this->redirector->getUrlGenerator(); + + if ($this->redirect) { + return $url->to($this->redirect); + } elseif ($this->redirectRoute) { + return $url->route($this->redirectRoute); + } elseif ($this->redirectAction) { + return $url->action($this->redirectAction); + } + + return $url->previous(); + } + + /** + * Determine if the request passes the authorization check. + * + * @return bool + */ + protected function passesAuthorization() + { + if (method_exists($this, 'authorize')) { + return $this->container->call([$this, 'authorize']); + } + + return false; + } + /** * Handle a failed authorization attempt. * @@ -38,4 +230,52 @@ protected function failedAuthorization() parent::failedAuthorization(); } + + /** + * Get custom messages for validator errors. + * + * @return array + */ + public function messages() + { + return []; + } + + /** + * Get custom attributes for validator errors. + * + * @return array + */ + public function attributes() + { + return []; + } + + /** + * Set the Redirector instance. + * + * @param Redirector $redirector + * + * @return $this + */ + public function setRedirector(Redirector $redirector) + { + $this->redirector = $redirector; + + return $this; + } + + /** + * Set the container implementation. + * + * @param \Illuminate\Contracts\Container\Container $container + * + * @return $this + */ + public function setContainer(Container $container) + { + $this->container = $container; + + return $this; + } } diff --git a/src/Provider/LumenServiceProvider.php b/src/Provider/LumenServiceProvider.php index 3b71381..b1558ad 100644 --- a/src/Provider/LumenServiceProvider.php +++ b/src/Provider/LumenServiceProvider.php @@ -3,6 +3,9 @@ namespace Dingo\Api\Provider; use ReflectionClass; +use Laravel\Lumen\Application; +use Dingo\Api\Http\FormRequest; +use Laravel\Lumen\Http\Redirector; use Dingo\Api\Http\Middleware\Auth; use Dingo\Api\Http\Middleware\Request; use Dingo\Api\Http\Middleware\RateLimit; @@ -11,6 +14,7 @@ use FastRoute\RouteParser\Std as StdRouteParser; use Illuminate\Http\Request as IlluminateRequest; use Dingo\Api\Routing\Adapter\Lumen as LumenAdapter; +use Illuminate\Contracts\Validation\ValidatesWhenResolved; use FastRoute\DataGenerator\GroupCountBased as GcbDataGenerator; class LumenServiceProvider extends DingoServiceProvider @@ -18,6 +22,8 @@ class LumenServiceProvider extends DingoServiceProvider /** * Boot the service provider. * + * @throws \ReflectionException + * * @return void */ public function boot() @@ -48,6 +54,16 @@ public function boot() }); }); + $this->app->afterResolving(ValidatesWhenResolved::class, function ($resolved) { + $resolved->validate(); + }); + + $this->app->resolving(FormRequest::class, function (FormRequest $request, Application $app) { + $this->initializeRequest($request, $app['request']); + + $request->setContainer($app)->setRedirector($app->make(Redirector::class)); + }); + $this->app->routeMiddleware([ 'api.auth' => Auth::class, 'api.throttle' => RateLimit::class, @@ -131,4 +147,39 @@ protected function gatherAppMiddleware(ReflectionClass $reflection) return $middleware; } + + /** + * Initialize the form request with data from the given request. + * + * @param FormRequest $form + * @param IlluminateRequest $current + * + * @return void + */ + protected function initializeRequest(FormRequest $form, IlluminateRequest $current) + { + $files = $current->files->all(); + + $files = is_array($files) ? array_filter($files) : $files; + + $form->initialize( + $current->query->all(), + $current->request->all(), + $current->attributes->all(), + $current->cookies->all(), + $files, + $current->server->all(), + $current->getContent() + ); + + $form->setJson($current->json()); + + if ($session = $current->getSession()) { + $form->setLaravelSession($session); + } + + $form->setUserResolver($current->getUserResolver()); + + $form->setRouteResolver($current->getRouteResolver()); + } }