diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 13eef56..4b9f797 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -3,6 +3,8 @@ namespace App\Exceptions; use Exception; +use Illuminate\Support\Arr; +use Illuminate\Support\Str; use Illuminate\Http\JsonResponse; use Illuminate\Validation\ValidationException; use Illuminate\Auth\Access\AuthorizationException; @@ -29,8 +31,7 @@ class Handler extends ExceptionHandler * * This is a great spot to send exceptions to Sentry, Bugsnag, etc. * - * @param \Exception $e - * @return void + * @param \Exception $e */ public function report(Exception $e) { @@ -40,18 +41,38 @@ public function report(Exception $e) /** * Render an exception into an HTTP response. * - * @param \Illuminate\Http\Request $request - * @param \Exception $e + * @param \Illuminate\Http\Request $request + * @param \Exception $e + * * @return \Illuminate\Http\Response */ public function render($request, Exception $e) { if ($e instanceof HttpException) { return new JsonResponse([ - 'message' => $e->getMessage(), + 'message' => $e->getMessage() ?: $this->getMessageFromClassName($e), ], $e->getStatusCode()); } return parent::render($request, $e); } + + /** + * Get Message From Class Name. + * + * @param HttpException $e + * + * @return string + */ + protected function getMessageFromClassName(HttpException $e) + { + $class = get_class($e); + $file = Arr::last(explode('\\', $class)); + + return Str::snake(str_ireplace( + ['HttpException', 'Exception'], + ['', ''], + $file + )); + } } diff --git a/app/Http/Controllers/Auth/AuthController.php b/app/Http/Controllers/Auth/AuthController.php index 2e55d83..4701eda 100644 --- a/app/Http/Controllers/Auth/AuthController.php +++ b/app/Http/Controllers/Auth/AuthController.php @@ -2,10 +2,10 @@ namespace App\Http\Controllers\Auth; -use JWTAuth; use Illuminate\Http\Request; use Illuminate\Http\Response; use Illuminate\Http\JsonResponse; +use Tymon\JWTAuth\Facades\JWTAuth; use App\Http\Controllers\Controller; use Tymon\JWTAuth\Exceptions\JWTException; use Illuminate\Http\Exception\HttpResponseException; @@ -22,43 +22,88 @@ class AuthController extends Controller public function postLogin(Request $request) { try { - $this->validate($request, [ - 'email' => 'required|email|max:255', - 'password' => 'required', - ]); + $this->validatePostLoginRequest($request); } catch (HttpResponseException $e) { - return new JsonResponse([ - 'error' => [ - 'message' => 'invalid_auth', - 'status_code' => Response::HTTP_BAD_REQUEST, - ], - ], Response::HTTP_BAD_REQUEST); + return $this->onBadRequest(); } - $credentials = $this->getCredentials($request); - try { // Attempt to verify the credentials and create a token for the user - if (!$token = JWTAuth::attempt($credentials)) { - return new JsonResponse([ - 'error' => [ - 'message' => 'invalid_credentials', - ], - ], Response::HTTP_UNAUTHORIZED); + if (!$token = JWTAuth::attempt( + $this->getCredentials($request) + )) { + return $this->onUnauthorized(); } } catch (JWTException $e) { // Something went wrong whilst attempting to encode the token - return new JsonResponse([ - 'error' => [ - 'message' => 'could_not_create_token', - ], - ], Response::HTTP_INTERNAL_SERVER_ERROR); + return $this->onJwtGenerationError(); } // All good so return the token + return $this->onAuthorized($token); + } + + /** + * Validate authentication request. + * + * @param Request $request + * @return void + * @throws HttpResponseException + */ + protected function validatePostLoginRequest(Request $request) + { + $this->validate($request, [ + 'email' => 'required|email|max:255', + 'password' => 'required', + ]); + } + + /** + * What response should be returned on bad request. + * + * @return JsonResponse + */ + protected function onBadRequest() + { return new JsonResponse([ - 'success' => [ - 'message' => 'token_generated', + 'message' => 'invalid_credentials' + ], Response::HTTP_BAD_REQUEST); + } + + /** + * What response should be returned on invalid credentials. + * + * @return JsonResponse + */ + protected function onUnauthorized() + { + return new JsonResponse([ + 'message' => 'invalid_credentials' + ], Response::HTTP_UNAUTHORIZED); + } + + /** + * What response should be returned on error while generate JWT. + * + * @return JsonResponse + */ + protected function onJwtGenerationError() + { + return new JsonResponse([ + 'message' => 'could_not_create_token' + ], Response::HTTP_INTERNAL_SERVER_ERROR); + } + + /** + * What response should be returned on authorized. + * + * @return JsonResponse + */ + protected function onAuthorized($token) + { + return new JsonResponse([ + 'message' => 'token_generated', + 'data' => [ 'token' => $token, ] ]); @@ -103,7 +148,9 @@ public function patchRefresh() return new JsonResponse([ 'message' => 'token_refreshed', - 'token' => $newToken + 'data' => [ + 'token' => $newToken + ] ]); } @@ -115,9 +162,8 @@ public function patchRefresh() public function getUser() { return new JsonResponse([ - 'success' => [ - 'user' => JWTAuth::parseToken()->authenticate() - ] + 'message' => 'authenticated_user', + 'data' => JWTAuth::parseToken()->authenticate() ]); } } diff --git a/app/Http/Middleware/CORSMiddleware.php b/app/Http/Middleware/CORSMiddleware.php new file mode 100644 index 0000000..57489aa --- /dev/null +++ b/app/Http/Middleware/CORSMiddleware.php @@ -0,0 +1,86 @@ +isPreflightRequest($request) + && $this->canBeConvertedToPreflightResponse($response)) { + $response = $this->createEmptyResponse(); + } + + return $this->addCorsHeaders($request, $response); + } + + /** + * Determine if request is a preflight request. + * + * @param \Illiminate\Http\Request $request + * + * @return bool + */ + protected function isPreflightRequest($request) + { + return $request->isMethod('OPTIONS'); + } + + /** + * Determine if response is not an error. + * + * @param \Illiminate\Http\Response $response + * + * @return bool + */ + protected function canBeConvertedToPreflightResponse($response) + { + return ($response->isSuccessful() || $response->isClientError()) + && !$response->isNotFound(); + } + + /** + * Create empty response for preflight request. + * + * @return \Illiminate\Http\Response + */ + protected function createEmptyResponse() + { + return new Response(null, 204); + } + + /** + * Add CORS headers. + * + * @param \Illiminate\Http\Request $request + * @param \Illiminate\Http\Response $response + */ + protected function addCorsHeaders($request, $response) + { + foreach ([ + 'Access-Control-Allow-Origin' => '*', + 'Access-Control-Max-Age' => (60 * 60 * 24), + 'Access-Control-Allow-Headers' => $request->header('Access-Control-Request-Headers'), + 'Access-Control-Allow-Methods' => $request->header('Access-Control-Request-Methods') + ?: 'GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS', + 'Access-Control-Allow-Credentials' => 'true', + ] as $header => $value) { + $response->header($header, $value); + } + + return $response; + } +} diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index aeb2b56..ddec046 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -2,7 +2,6 @@ namespace App\Providers; -use Illuminate\Cache\CacheManager; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider @@ -14,10 +13,6 @@ class AppServiceProvider extends ServiceProvider */ public function register() { - $this->app->singleton([CacheManager::class => 'cache'], function ($app) { - $app->configure('cache'); - - return new CacheManager($app); - }); + // } } diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index e6e45c7..9502a0b 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -15,7 +15,7 @@ class AuthServiceProvider extends ServiceProvider */ public function register() { - $this->app->alias('auth', 'Illuminate\Auth\AuthManager'); + // } /** @@ -30,10 +30,10 @@ public function boot() // should return either a User instance or null. You're free to obtain // the User instance via an API token or any other method necessary. - // $this->app['auth']->viaRequest('api', function ($request) { - // if ($request->input('api_token')) { - // return User::where('api_token', $request->input('api_token'))->first(); - // } - // }); + $this->app['auth']->viaRequest('api', function ($request) { + if ($request->input('api_token')) { + return User::where('api_token', $request->input('api_token'))->first(); + } + }); } } diff --git a/app/Providers/GuardServiceProvider.php b/app/Providers/GuardServiceProvider.php index f30dd28..adce6a7 100644 --- a/app/Providers/GuardServiceProvider.php +++ b/app/Providers/GuardServiceProvider.php @@ -14,11 +14,11 @@ class GuardServiceProvider extends ServiceProvider */ public function register() { - // $this->app->make('auth')->extend('api', function ($app, $name, array $config) { - // return new ApiGuard( - // $app->make('auth')->createUserProvider($config['provider']), - // $app->make('request') - // ); - // }); + $this->app->make('auth')->extend('api', function ($app, $name, array $config) { + return new ApiGuard( + $app->make('auth')->createUserProvider($config['provider']), + $app->make('request') + ); + }); } } diff --git a/app/Providers/LumenJWTServiceProvider.php b/app/Providers/LumenJWTServiceProvider.php new file mode 100644 index 0000000..9f8130f --- /dev/null +++ b/app/Providers/LumenJWTServiceProvider.php @@ -0,0 +1,356 @@ +registerJWTAuthDependency(); + + // JWT itself + $this->registerJWTServiceProvider(); + + // Middleware route registration + $this->registerJwtAuthMiddleware(); + } + + /** + * Here we do some internal function to fulfill JWTAuth dependency. + */ + protected function registerJWTAuthDependency() + { + $this->registerRoutingAlias(); + + $this->registerSessionServiceProvider(); + + $this->registerCookieComponent(); + + $this->registerCacheServiceProvider(); + + $this->registerAuthManagerAlias(); + } + + /** + * Let's alias this route. Since Lumen doesn't use Illuminate Route component, + * we can safely using base response instance to 'hack' JWT Auth dependency. + */ + protected function registerRoutingAlias() + { + $this->app->singleton( + ResponseFactoryContract::class, + ResponseFactory::class + ); + } + + /** + * Register session to application. + */ + protected function registerSessionServiceProvider() + { + $this->registerSessionManager(); + + $this->registerSessionStore(); + } + + protected function registerSessionManager() + { + $this->loadComponent( + [SessionManager::class => 'session'], + 'SessionManager' + ); + } + + protected function registerSessionStore() + { + $this->loadComponent( + [Store::class => 'session.store'], + 'SessionStore' + ); + } + + /** + * Load session manager component. + * + * @return Closure + */ + protected function loadSessionManagerComponent() + { + return function ($app) { + return $app->loadComponent( + 'session', + SessionServiceProvider::class + ); + }; + } + + /** + * Load session store component. + * + * @return Closure + */ + protected function loadSessionStoreComponent() + { + return function ($app) { + return $app->loadComponent( + 'session', + SessionServiceProvider::class, + 'session.store' + ); + }; + } + + /** + * Register cookie to application. + */ + protected function registerCookieComponent() + { + $this->loadComponent( + [CookieJar::class => 'cookie'], + 'CookieJar' + ); + } + + /** + * Load cookie component. + * + * @return Closure + */ + protected function loadCookieJarComponent() + { + return function ($app) { + return new CookieJar(); + }; + } + + /** + * Register cache to application. + */ + protected function registerCacheServiceProvider() + { + $this->registerCacheManager(); + + $this->registerMemcachedConnector(); + } + + /** + * Register cache manager. + */ + protected function registerCacheManager() + { + $this->loadComponent( + [CacheManager::class => 'cache'], + 'CacheManager' + ); + } + + /** + * Register memcached connector. + */ + protected function registerMemcachedConnector() + { + $this->loadComponent( + [MemcachedConnector::class => 'memcached.connector'], + 'MemcachedConnector' + ); + } + + /** + * Load cache manager component. + * + * @return Closure + */ + protected function loadCacheManagerComponent() + { + return function ($app) { + $app->configure('cache'); + + return new CacheManager($app); + }; + } + + /** + * Load memcached connector component. + * + * @return Closure + */ + protected function loadMemcachedConnectorComponent() + { + return function ($app) { + return new MemcachedConnector(); + }; + } + + /** + * Register auth manager to application. + */ + protected function registerAuthManagerAlias() + { + $this->app->alias('auth', AuthManager::class); + } + + /** + * Register JWTAuth to application. + */ + protected function registerJWTServiceProvider() + { + $this->registerJwtAuth(); + + $this->registerJWTFacades(); + } + + /** + * Register JWTAuth resolver. + */ + protected function registerJwtAuth() + { + $this->registerBaseJWTAuth(); + + $this->registerJwtAuthProvider(); + } + + /** + * Register JWTAuth base instance resolver. + */ + protected function registerBaseJWTAuth() + { + $this->loadComponent( + [TymonJWTAuth::class => 'tymon.jwt.auth'], + 'JWTAuth' + ); + } + + /** + * Register JWTAuthProvider instance resolver. + */ + protected function registerJwtAuthProvider() + { + $this->loadComponent( + [JWTInterface::class => 'tymon.jwt.provider.jwt'], + 'JWTAuthProvider' + ); + } + + /** + * Load JWT Auth component. + * + * @return Closure + */ + protected function loadJWTAuthComponent() + { + return function ($app) { + return $app->loadComponent( + 'jwt', + JWTAuthServiceProvider::class, + TymonJWTAuth::class + ); + }; + } + + /** + * Load JWT Auth component. + * + * @return Closure + */ + protected function loadJWTAuthProviderComponent() + { + return function ($app) { + return $app->loadComponent( + 'jwt', + JWTAuthServiceProvider::class, + JWTInterface::class + ); + }; + } + + /** + * Register JWTAuth facades. + */ + protected function registerJWTFacades() + { + if ($this->shouldRegisterFacades()) { + class_alias(JWTAuthFacade::class, JWTAuth::class); + class_alias(JWTFactoryFacade::class, JWTFactory::class); + } + } + + /** + * Determine if we should register JWT Auth facades. + * + * @return bool + */ + protected function shouldRegisterFacades() + { + return $this->isUsingFacade() === true + && $this->facadeHasNotBeenRegistered() === true; + } + + /** + * Determine if application is using facade. + * + * @return bool + */ + protected function isUsingFacade() + { + return Facade::getFacadeApplication() !== null; + } + + /** + * Determine if JWT Auth facade has not been registered. + * + * @return bool + */ + protected function facadeHasNotBeenRegistered() + { + return class_exists(JWTAuthFacade::class) === false; + } + + /** + * Register JWTAuth middleware. + */ + protected function registerJwtAuthMiddleware() + { + $this->app->routeMiddleware([ + 'jwt.auth' => GetUserFromToken::class, + 'jwt.refresh' => RefreshToken::class, + ]); + } + + /** + * Load component by given bindings an name resolver. + * + * @param array $bindings + * @param string $name + */ + protected function loadComponent(array $bindings, $name) + { + $this->app->singleton( + $bindings, + $this->{"load{$name}Component"}() + ); + } +} diff --git a/bootstrap/app.php b/bootstrap/app.php index a91cd8e..b88e829 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -42,7 +42,6 @@ try { (new Dotenv\Dotenv(__DIR__.'/../'))->load(); } catch (Dotenv\Exception\InvalidPathException $e) { - // } /* @@ -62,9 +61,6 @@ $app->withFacades(); -class_exists(JWTAuth::class) or class_alias(Tymon\JWTAuth\Facades\JWTAuth::class, JWTAuth::class); -class_exists(JWTFactory::class) or class_alias(Tymon\JWTAuth\Facades\JWTFactory::class, JWTFactory::class); - $app->withEloquent(); /* @@ -88,11 +84,6 @@ class_exists(JWTFactory::class) or class_alias(Tymon\JWTAuth\Facades\JWTFactory: App\Console\Kernel::class ); -$app->singleton( - Illuminate\Contracts\Routing\ResponseFactory::class, - Illuminate\Routing\ResponseFactory::class -); - /* |-------------------------------------------------------------------------- | Register Middleware @@ -104,14 +95,12 @@ class_exists(JWTFactory::class) or class_alias(Tymon\JWTAuth\Facades\JWTFactory: | */ -// $app->middleware([ -// App\Http\Middleware\ExampleMiddleware::class -// ]); +$app->middleware([ + App\Http\Middleware\CORSMiddleware::class +]); $app->routeMiddleware([ - // 'auth' => App\Http\Middleware\Authenticate::class, - 'jwt.auth' => Tymon\JWTAuth\Middleware\GetUserFromToken::class, - 'jwt.refresh' => Tymon\JWTAuth\Middleware\RefreshToken::class, + // 'auth' => App\Http\Middleware\Authenticate::class, ]); /* @@ -125,21 +114,25 @@ class_exists(JWTFactory::class) or class_alias(Tymon\JWTAuth\Facades\JWTFactory: | */ -// JWTAuth Dependency -$app->configure('session'); -$app->register(Illuminate\Session\SessionServiceProvider::class); -$app->register(Illuminate\Cookie\CookieServiceProvider::class); -$app->register(Illuminate\Cache\CacheServiceProvider::class); - -$app->register(App\Providers\AppServiceProvider::class); -$app->register(App\Providers\AuthServiceProvider::class); +// $app->register(App\Providers\AppServiceProvider::class); +// $app->register(App\Providers\AuthServiceProvider::class); // $app->register(App\Providers\GuardServiceProvider::class); // $app->register(App\Providers\EventServiceProvider::class); // JWTAuth -$app->configure('jwt'); -$app->register(Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class); +$app->register(App\Providers\LumenJWTServiceProvider::class); + +// Dingo +$app->register(Dingo\Api\Provider\LumenServiceProvider::class); + +// Configure our JWT for Dingo +$app->make(Dingo\Api\Auth\Auth::class)->extend('jwt', function ($app) { + return new Dingo\Api\Auth\Provider\JWT( + $app->make(Tymon\JWTAuth\JWTAuth::class) + ); +}); +// Lumen Generator disabled it on production if you want $app->register(Flipbox\LumenGenerator\LumenGeneratorServiceProvider::class); /* @@ -154,7 +147,7 @@ class_exists(JWTFactory::class) or class_alias(Tymon\JWTAuth\Facades\JWTFactory: */ $app->group(['namespace' => 'App\Http\Controllers'], function ($app) { - require __DIR__.'/../routes/api.php'; + require $app->basePath('/routes/api.php'); }); return $app; diff --git a/composer.json b/composer.json index 8494c57..517562f 100644 --- a/composer.json +++ b/composer.json @@ -8,16 +8,16 @@ "php": ">=5.5.9", "laravel/lumen-framework": "^5.3", "vlucas/phpdotenv": "~2.2", - "illuminate/routing": "^5.3", "illuminate/hashing": "^5.3", "tymon/jwt-auth": "0.5.*", "illuminate/cookie": "^5.3", - "flipbox/lumen-generator": "^5.3" + "flipbox/lumen-generator": "^5.3", + "illuminate/routing": "^5.3", + "dingo/api": "1.0.x@dev" }, "require-dev": { "fzaninotto/faker": "~1.4", - "phpunit/phpunit": "~4.0", - "symfony/var-dumper": "^3.0" + "phpunit/phpunit": "~4.0" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 9531a31..201fcbb 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "413cc26a4ec99cf2a02527d02d29a6ae", - "content-hash": "25e59a0036531efa7dc89ad4b580dbbf", + "hash": "91c16c68582554d7675efafe0ba6d76c", + "content-hash": "dc596697f1f0901aab78b4cb4d03b05f", "packages": [ { "name": "appzcoder/lumen-routes-list", @@ -103,6 +103,137 @@ ], "time": "2015-11-09 22:51:51" }, + { + "name": "dingo/api", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/dingo/api.git", + "reference": "dc312a566ff8fe16098f95360d3778789727f63f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dingo/api/zipball/dc312a566ff8fe16098f95360d3778789727f63f", + "reference": "dc312a566ff8fe16098f95360d3778789727f63f", + "shasum": "" + }, + "require": { + "dingo/blueprint": "0.2.*", + "doctrine/annotations": "1.2.*", + "illuminate/routing": "5.1.* || 5.2.* || 5.3.*", + "illuminate/support": "5.1.* || 5.2.* || 5.3.*", + "league/fractal": ">=0.12.0", + "php": "^5.5.9 || ^7.0" + }, + "require-dev": { + "illuminate/auth": "5.1.* || 5.2.* || 5.3.*", + "illuminate/cache": "5.1.* || 5.2.* || 5.3.*", + "illuminate/console": "5.1.* || 5.2.* || 5.3.*", + "illuminate/database": "5.1.* || 5.2.* || 5.3.*", + "illuminate/events": "5.1.* || 5.2.* || 5.3.*", + "illuminate/filesystem": "5.1.* || 5.2.* || 5.3.*", + "illuminate/log": "5.1.* || 5.2.* || 5.3.*", + "illuminate/pagination": "5.1.* || 5.2.* || 5.3.*", + "laravel/lumen-framework": "5.1.* || 5.2.*", + "lucadegasperi/oauth2-server-laravel": "5.0.*", + "mockery/mockery": "~0.9", + "phpunit/phpunit": "^4.8 || ^5.0", + "squizlabs/php_codesniffer": "~2.0", + "tymon/jwt-auth": "1.0.*" + }, + "suggest": { + "lucadegasperi/oauth2-server-laravel": "Protect your API with OAuth 2.0.", + "tymon/jwt-auth": "Protect your API with JSON Web Tokens." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Dingo\\Api\\": "src/" + }, + "files": [ + "src/helpers.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jason Lewis", + "email": "jason.lewis1991@gmail.com" + } + ], + "description": "A RESTful API package for the Laravel and Lumen frameworks.", + "keywords": [ + "api", + "dingo", + "laravel", + "restful" + ], + "time": "2016-10-18 16:20:39" + }, + { + "name": "dingo/blueprint", + "version": "v0.2.0", + "source": { + "type": "git", + "url": "https://github.com/dingo/blueprint.git", + "reference": "d37fb7433aeadb3d40d5e790978c3c8d229d0e7d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dingo/blueprint/zipball/d37fb7433aeadb3d40d5e790978c3c8d229d0e7d", + "reference": "d37fb7433aeadb3d40d5e790978c3c8d229d0e7d", + "shasum": "" + }, + "require": { + "doctrine/annotations": "1.2.*", + "illuminate/filesystem": "5.1.* || 5.2.* || 5.3.*", + "illuminate/support": "5.1.* || 5.2.* || 5.3.*", + "php": ">=5.5.9", + "phpdocumentor/reflection-docblock": "3.1.*" + }, + "require-dev": { + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.2-dev" + } + }, + "autoload": { + "psr-4": { + "Dingo\\Blueprint\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jason Lewis", + "email": "jason.lewis1991@gmail.com" + } + ], + "description": "API Blueprint documentation generator.", + "keywords": [ + "api", + "blueprint", + "dingo", + "docs", + "laravel" + ], + "time": "2016-08-30 03:27:49" + }, { "name": "dnoegel/php-xdg-base-dir", "version": "0.1", @@ -136,6 +267,74 @@ "description": "implementation of xdg base directory specification for php", "time": "2014-10-24 07:27:01" }, + { + "name": "doctrine/annotations", + "version": "v1.2.7", + "source": { + "type": "git", + "url": "https://github.com/doctrine/annotations.git", + "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/f25c8aab83e0c3e976fd7d19875f198ccf2f7535", + "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535", + "shasum": "" + }, + "require": { + "doctrine/lexer": "1.*", + "php": ">=5.3.2" + }, + "require-dev": { + "doctrine/cache": "1.*", + "phpunit/phpunit": "4.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\Common\\Annotations\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Docblock Annotations Parser", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "annotations", + "docblock", + "parser" + ], + "time": "2015-08-31 12:32:49" + }, { "name": "doctrine/inflector", "version": "v1.1.0", @@ -203,6 +402,60 @@ ], "time": "2015-11-06 14:35:42" }, + { + "name": "doctrine/lexer", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\Common\\Lexer\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "lexer", + "parser" + ], + "time": "2014-09-09 13:34:57" + }, { "name": "flipbox/lumen-generator", "version": "5.3.2", @@ -1573,6 +1826,69 @@ ], "time": "2016-10-05 22:29:03" }, + { + "name": "league/fractal", + "version": "0.14.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/fractal.git", + "reference": "56ad8933fbb40328ca3321c84143b2c16186eebf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/fractal/zipball/56ad8933fbb40328ca3321c84143b2c16186eebf", + "reference": "56ad8933fbb40328ca3321c84143b2c16186eebf", + "shasum": "" + }, + "require": { + "php": ">=5.4" + }, + "require-dev": { + "illuminate/contracts": "~5.0", + "mockery/mockery": "~0.9", + "pagerfanta/pagerfanta": "~1.0.0", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~1.5", + "zendframework/zend-paginator": "~2.3" + }, + "suggest": { + "illuminate/pagination": "The Illuminate Pagination component.", + "pagerfanta/pagerfanta": "Pagerfanta Paginator", + "zendframework/zend-paginator": "Zend Framework Paginator" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.13-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Fractal\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Phil Sturgeon", + "email": "me@philsturgeon.uk", + "homepage": "http://philsturgeon.uk/", + "role": "Developer" + } + ], + "description": "Handle the output of complex data structures ready for API output.", + "homepage": "http://fractal.thephpleague.com/", + "keywords": [ + "api", + "json", + "league", + "rest" + ], + "time": "2016-07-21 09:56:14" + }, { "name": "monolog/monolog", "version": "1.21.0", @@ -1934,6 +2250,152 @@ ], "time": "2016-10-17 15:23:22" }, + { + "name": "phpdocumentor/reflection-common", + "version": "1.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "time": "2015-12-27 11:43:31" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e", + "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e", + "shasum": "" + }, + "require": { + "php": ">=5.5", + "phpdocumentor/reflection-common": "^1.0@dev", + "phpdocumentor/type-resolver": "^0.2.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^4.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2016-09-30 07:12:33" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "0.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b39c7a5b194f9ed7bd0dd345c751007a41862443", + "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443", + "shasum": "" + }, + "require": { + "php": ">=5.5", + "phpdocumentor/reflection-common": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "time": "2016-06-10 07:14:17" + }, { "name": "phpseclib/phpseclib", "version": "0.3.10", @@ -2214,7 +2676,7 @@ }, { "name": "symfony/debug", - "version": "v3.1.5", + "version": "v3.1.6", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", @@ -2271,16 +2733,16 @@ }, { "name": "symfony/event-dispatcher", - "version": "v3.1.5", + "version": "v3.1.6", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "c0c00c80b3a69132c4e55c3e7db32b4a387615e5" + "reference": "28b0832b2553ffb80cabef6a7a812ff1e670c0bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c0c00c80b3a69132c4e55c3e7db32b4a387615e5", - "reference": "c0c00c80b3a69132c4e55c3e7db32b4a387615e5", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/28b0832b2553ffb80cabef6a7a812ff1e670c0bc", + "reference": "28b0832b2553ffb80cabef6a7a812ff1e670c0bc", "shasum": "" }, "require": { @@ -2327,11 +2789,11 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2016-07-19 10:45:57" + "time": "2016-10-13 06:28:43" }, { "name": "symfony/finder", - "version": "v3.1.5", + "version": "v3.1.6", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", @@ -2380,16 +2842,16 @@ }, { "name": "symfony/http-foundation", - "version": "v3.1.5", + "version": "v3.1.6", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "5114f1becca9f29e3af94374f1689c83c1aa3d97" + "reference": "f21e5a8b88274b7720779aa88f9c02c6d6ec08d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/5114f1becca9f29e3af94374f1689c83c1aa3d97", - "reference": "5114f1becca9f29e3af94374f1689c83c1aa3d97", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/f21e5a8b88274b7720779aa88f9c02c6d6ec08d7", + "reference": "f21e5a8b88274b7720779aa88f9c02c6d6ec08d7", "shasum": "" }, "require": { @@ -2429,20 +2891,20 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2016-09-21 20:55:10" + "time": "2016-10-24 15:52:44" }, { "name": "symfony/http-kernel", - "version": "v3.1.5", + "version": "v3.1.6", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "dc339d6eebadfa6e39c52868b4d4a715eff13c69" + "reference": "c235f1b13ba67012e283996a5427f22e2e04be14" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/dc339d6eebadfa6e39c52868b4d4a715eff13c69", - "reference": "dc339d6eebadfa6e39c52868b4d4a715eff13c69", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/c235f1b13ba67012e283996a5427f22e2e04be14", + "reference": "c235f1b13ba67012e283996a5427f22e2e04be14", "shasum": "" }, "require": { @@ -2450,7 +2912,7 @@ "psr/log": "~1.0", "symfony/debug": "~2.8|~3.0", "symfony/event-dispatcher": "~2.8|~3.0", - "symfony/http-foundation": "~2.8.8|~3.0.8|~3.1.2|~3.2" + "symfony/http-foundation": "~2.8.13|~3.1.6|~3.2" }, "conflict": { "symfony/config": "<2.8" @@ -2511,7 +2973,7 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2016-10-03 19:01:06" + "time": "2016-10-27 02:38:31" }, { "name": "symfony/polyfill-mbstring", @@ -2623,7 +3085,7 @@ }, { "name": "symfony/routing", - "version": "v3.1.5", + "version": "v3.1.6", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", @@ -2698,16 +3160,16 @@ }, { "name": "symfony/translation", - "version": "v3.1.5", + "version": "v3.1.6", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "93013a18d272e59dab8e67f583155b78c68947eb" + "reference": "ff1285087397d2f64041b35e591f3025881c90cd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/93013a18d272e59dab8e67f583155b78c68947eb", - "reference": "93013a18d272e59dab8e67f583155b78c68947eb", + "url": "https://api.github.com/repos/symfony/translation/zipball/ff1285087397d2f64041b35e591f3025881c90cd", + "reference": "ff1285087397d2f64041b35e591f3025881c90cd", "shasum": "" }, "require": { @@ -2758,7 +3220,7 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2016-09-06 11:02:40" + "time": "2016-10-18 04:30:12" }, { "name": "symfony/var-dumper", @@ -2935,6 +3397,56 @@ "environment" ], "time": "2016-09-01 10:05:43" + }, + { + "name": "webmozart/assert", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "bb2d123231c095735130cc8f6d31385a44c7b308" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/bb2d123231c095735130cc8f6d31385a44c7b308", + "reference": "bb2d123231c095735130cc8f6d31385a44c7b308", + "shasum": "" + }, + "require": { + "php": "^5.3.3|^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2016-08-09 15:02:57" } ], "packages-dev": [ @@ -3040,152 +3552,6 @@ ], "time": "2016-04-29 12:21:54" }, - { - "name": "phpdocumentor/reflection-common", - "version": "1.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", - "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", - "shasum": "" - }, - "require": { - "php": ">=5.5" - }, - "require-dev": { - "phpunit/phpunit": "^4.6" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "time": "2015-12-27 11:43:31" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "3.1.1", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e", - "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e", - "shasum": "" - }, - "require": { - "php": ">=5.5", - "phpdocumentor/reflection-common": "^1.0@dev", - "phpdocumentor/type-resolver": "^0.2.0", - "webmozart/assert": "^1.0" - }, - "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^4.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2016-09-30 07:12:33" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "0.2", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b39c7a5b194f9ed7bd0dd345c751007a41862443", - "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443", - "shasum": "" - }, - "require": { - "php": ">=5.5", - "phpdocumentor/reflection-common": "^1.0" - }, - "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^5.2||^4.8.24" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "time": "2016-06-10 07:14:17" - }, { "name": "phpspec/prophecy", "version": "v1.6.1", @@ -4039,61 +4405,13 @@ "description": "Symfony Yaml Component", "homepage": "https://symfony.com", "time": "2016-09-25 08:27:07" - }, - { - "name": "webmozart/assert", - "version": "1.1.0", - "source": { - "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "bb2d123231c095735130cc8f6d31385a44c7b308" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/bb2d123231c095735130cc8f6d31385a44c7b308", - "reference": "bb2d123231c095735130cc8f6d31385a44c7b308", - "shasum": "" - }, - "require": { - "php": "^5.3.3|^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "time": "2016-08-09 15:02:57" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "dingo/api": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/config/api.php b/config/api.php new file mode 100644 index 0000000..7b5c64a --- /dev/null +++ b/config/api.php @@ -0,0 +1,223 @@ + env('API_STANDARDS_TREE', 'x'), + + /* + |-------------------------------------------------------------------------- + | API Subtype + |-------------------------------------------------------------------------- + | + | Your subtype will follow the standards tree you use when used in the + | "Accept" header to negotiate the content type and version. + | + | For example: Accept: application/x.SUBTYPE.v1+json + | + */ + + 'subtype' => env('API_SUBTYPE', ''), + + /* + |-------------------------------------------------------------------------- + | Default API Version + |-------------------------------------------------------------------------- + | + | This is the default version when strict mode is disabled and your API + | is accessed via a web browser. It's also used as the default version + | when generating your APIs documentation. + | + */ + + 'version' => env('API_VERSION', 'v1'), + + /* + |-------------------------------------------------------------------------- + | Default API Prefix + |-------------------------------------------------------------------------- + | + | A default prefix to use for your API routes so you don't have to + | specify it for each group. + | + */ + + 'prefix' => env('API_PREFIX', null), + + /* + |-------------------------------------------------------------------------- + | Default API Domain + |-------------------------------------------------------------------------- + | + | A default domain to use for your API routes so you don't have to + | specify it for each group. + | + */ + + 'domain' => env('API_DOMAIN', null), + + /* + |-------------------------------------------------------------------------- + | Name + |-------------------------------------------------------------------------- + | + | When documenting your API using the API Blueprint syntax you can + | configure a default name to avoid having to manually specify + | one when using the command. + | + */ + + 'name' => env('API_NAME', null), + + /* + |-------------------------------------------------------------------------- + | Conditional Requests + |-------------------------------------------------------------------------- + | + | Globally enable conditional requests so that an ETag header is added to + | any successful response. Subsequent requests will perform a check and + | will return a 304 Not Modified. This can also be enabled or disabled + | on certain groups or routes. + | + */ + + 'conditionalRequest' => env('API_CONDITIONAL_REQUEST', true), + + /* + |-------------------------------------------------------------------------- + | Strict Mode + |-------------------------------------------------------------------------- + | + | Enabling strict mode will require clients to send a valid Accept header + | with every request. This also voids the default API version, meaning + | your API will not be browsable via a web browser. + | + */ + + 'strict' => env('API_STRICT', false), + + /* + |-------------------------------------------------------------------------- + | Debug Mode + |-------------------------------------------------------------------------- + | + | Enabling debug mode will result in error responses caused by thrown + | exceptions to have a "debug" key that will be populated with + | more detailed information on the exception. + | + */ + + 'debug' => env('API_DEBUG', false), + + /* + |-------------------------------------------------------------------------- + | Generic Error Format + |-------------------------------------------------------------------------- + | + | When some HTTP exceptions are not caught and dealt with the API will + | generate a generic error response in the format provided. Any + | keys that aren't replaced with corresponding values will be + | removed from the final response. + | + */ + + 'errorFormat' => [ + 'message' => ':message', + 'errors' => ':errors', + 'code' => ':code', + 'status_code' => ':status_code', + 'debug' => ':debug', + ], + + /* + |-------------------------------------------------------------------------- + | API Middleware + |-------------------------------------------------------------------------- + | + | Middleware that will be applied globally to all API requests. + | + */ + + 'middleware' => [ + + ], + + /* + |-------------------------------------------------------------------------- + | Authentication Providers + |-------------------------------------------------------------------------- + | + | The authentication providers that should be used when attempting to + | authenticate an incoming API request. + | + */ + + 'auth' => [ + 'jwt' => Dingo\Api\Auth\Provider\JWT::class, + ], + + /* + |-------------------------------------------------------------------------- + | Throttling / Rate Limiting + |-------------------------------------------------------------------------- + | + | Consumers of your API can be limited to the amount of requests they can + | make. You can create your own throttles or simply change the default + | throttles. + | + */ + + 'throttling' => [ + + ], + + /* + |-------------------------------------------------------------------------- + | Response Transformer + |-------------------------------------------------------------------------- + | + | Responses can be transformed so that they are easier to format. By + | default a Fractal transformer will be used to transform any + | responses prior to formatting. You can easily replace + | this with your own transformer. + | + */ + + 'transformer' => env('API_TRANSFORMER', Dingo\Api\Transformer\Adapter\Fractal::class), + + /* + |-------------------------------------------------------------------------- + | Response Formats + |-------------------------------------------------------------------------- + | + | Responses can be returned in multiple formats by registering different + | response formatters. You can also customize an existing response + | formatter. + | + */ + + 'defaultFormat' => env('API_DEFAULT_FORMAT', 'json'), + + 'formats' => [ + + 'json' => Dingo\Api\Http\Response\Format\Json::class, + + ], + +]; diff --git a/config/session.php b/config/session.php index ace3ef0..0f184bd 100644 --- a/config/session.php +++ b/config/session.php @@ -111,69 +111,4 @@ 'lottery' => [2, 100], - /* - |-------------------------------------------------------------------------- - | Session Cookie Name - |-------------------------------------------------------------------------- - | - | Here you may change the name of the cookie used to identify a session - | instance by ID. The name specified here will get used every time a - | new session cookie is created by the framework for every driver. - | - */ - - 'cookie' => 'laravel_session', - - /* - |-------------------------------------------------------------------------- - | Session Cookie Path - |-------------------------------------------------------------------------- - | - | The session cookie path determines the path for which the cookie will - | be regarded as available. Typically, this will be the root path of - | your application but you are free to change this when necessary. - | - */ - - 'path' => '/', - - /* - |-------------------------------------------------------------------------- - | Session Cookie Domain - |-------------------------------------------------------------------------- - | - | Here you may change the domain of the cookie used to identify a session - | in your application. This will determine which domains the cookie is - | available to in your application. A sensible default has been set. - | - */ - - 'domain' => env('SESSION_DOMAIN', null), - - /* - |-------------------------------------------------------------------------- - | HTTPS Only Cookies - |-------------------------------------------------------------------------- - | - | By setting this option to true, session cookies will only be sent back - | to the server if the browser has a HTTPS connection. This will keep - | the cookie from being sent to you if it can not be done securely. - | - */ - - 'secure' => false, - - /* - |-------------------------------------------------------------------------- - | HTTP Access Only - |-------------------------------------------------------------------------- - | - | Setting this value to true will prevent JavaScript from accessing the - | value of the cookie and the cookie will only be accessible through - | the HTTP protocol. You are free to modify this option if needed. - | - */ - - 'http_only' => true, - ]; diff --git a/readme.md b/readme.md index afa2e50..fee8d6e 100644 --- a/readme.md +++ b/readme.md @@ -4,9 +4,11 @@ Basically this is a starter kit for you to integrate Lumen with [JWT Authenticat ## What's Added -- [Lumen 5.3](https://github.com/laravel/lumen/tree/v5.3.0) -- [JWT Auth](https://github.com/tymondesigns/jwt-auth) for Lumen Application +- [Lumen 5.3](https://github.com/laravel/lumen/tree/v5.3.0). +- [JWT Auth](https://github.com/tymondesigns/jwt-auth) for Lumen Application. +- [Dingo](https://github.com/dingo/api) to easily and quickly build your own API. - [Lumen Generator](https://github.com/flipboxstudio/lumen-generator) to make development even easier and faster. +- [CORS and Preflight Request](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) support. ## Quick Start @@ -96,6 +98,10 @@ Response: +--------+------------------+---------------------+------------------------------------------+------------------+------------+ ``` +## Future + +I will make a standalone package that would works on your current project. + ## License ``` diff --git a/routes/api.php b/routes/api.php index 8c88d84..4b15f24 100644 --- a/routes/api.php +++ b/routes/api.php @@ -11,14 +11,32 @@ | */ -$app->post('/auth/login', ['uses' => 'Auth\AuthController@postLogin', 'as' => 'api.auth.login']); +$api = $app->make(Dingo\Api\Routing\Router::class); -$app->group([ - 'middleware' => 'jwt.auth', - 'namespace' => 'App\Http\Controllers' -], function ($app) { - $app->get('/', ['uses' => 'APIController@getIndex', 'as' => 'api.index']); - $app->get('/auth/user', ['uses' => 'Auth\AuthController@getUser', 'as' => 'api.auth.user']); - $app->patch('/auth/refresh', ['uses' => 'Auth\AuthController@patchRefresh', 'as' => 'api.auth.refresh']); - $app->delete('/auth/invalidate', ['uses' => 'Auth\AuthController@deleteInvalidate', 'as' => 'api.auth.invalidate']); +$api->version('v1', function ($api) { + $api->post('/auth/login', [ + 'as' => 'api.auth.login', + 'uses' => 'App\Http\Controllers\Auth\AuthController@postLogin', + ]); + + $api->group([ + 'middleware' => 'api.auth', + ], function ($api) { + $api->get('/', [ + 'uses' => 'App\Http\Controllers\APIController@getIndex', + 'as' => 'api.index' + ]); + $api->get('/auth/user', [ + 'uses' => 'App\Http\Controllers\Auth\AuthController@getUser', + 'as' => 'api.auth.user' + ]); + $api->patch('/auth/refresh', [ + 'uses' => 'App\Http\Controllers\Auth\AuthController@patchRefresh', + 'as' => 'api.auth.refresh' + ]); + $api->delete('/auth/invalidate', [ + 'uses' => 'App\Http\Controllers\Auth\AuthController@deleteInvalidate', + 'as' => 'api.auth.invalidate' + ]); + }); });