From 69b517ea79560eb82cb9702ee16880a64054f090 Mon Sep 17 00:00:00 2001 From: Franz Liedke Date: Fri, 30 Jun 2017 12:07:20 +0200 Subject: [PATCH] Get rid of Server classes for Admin, API and Forum The various middleware can be registered in the service provider, and the rest of the logic can all go through one single front controller (index.php in flarum/flarum, and Flarum\Http\Server in flarum/core). This will also simplify the necessary server setup, as only one rewrite rule remains. --- src/Admin/AdminServiceProvider.php | 33 ++++++ src/Admin/Server.php | 58 ----------- src/Api/ApiServiceProvider.php | 32 ++++++ src/Api/Server.php | 62 ----------- src/Event/ConfigureMiddleware.php | 27 ++--- src/Forum/ForumServiceProvider.php | 31 ++++++ src/Forum/Server.php | 61 ----------- src/Http/AbstractServer.php | 81 --------------- src/Http/FullStackServer.php | 37 ------- src/Http/Server.php | 159 +++++++++++++++++++++++++++++ 10 files changed, 263 insertions(+), 318 deletions(-) delete mode 100644 src/Admin/Server.php delete mode 100644 src/Api/Server.php delete mode 100644 src/Forum/Server.php delete mode 100644 src/Http/AbstractServer.php delete mode 100644 src/Http/FullStackServer.php create mode 100644 src/Http/Server.php diff --git a/src/Admin/AdminServiceProvider.php b/src/Admin/AdminServiceProvider.php index 913c6493a..f7da26d04 100644 --- a/src/Admin/AdminServiceProvider.php +++ b/src/Admin/AdminServiceProvider.php @@ -11,13 +11,23 @@ namespace Flarum\Admin; +use Flarum\Admin\Middleware\RequireAdministrateAbility; +use Flarum\Event\ConfigureMiddleware; use Flarum\Extension\Event\Disabled; use Flarum\Extension\Event\Enabled; use Flarum\Foundation\AbstractServiceProvider; +use Flarum\Http\Middleware\AuthenticateWithSession; +use Flarum\Http\Middleware\DispatchRoute; +use Flarum\Http\Middleware\HandleErrors; +use Flarum\Http\Middleware\ParseJsonBody; +use Flarum\Http\Middleware\RememberFromCookie; +use Flarum\Http\Middleware\SetLocale; +use Flarum\Http\Middleware\StartSession; use Flarum\Http\RouteCollection; use Flarum\Http\RouteHandlerFactory; use Flarum\Http\UrlGenerator; use Flarum\Settings\Event\Saved; +use Zend\Stratigility\MiddlewarePipe; class AdminServiceProvider extends AbstractServiceProvider { @@ -33,6 +43,29 @@ class AdminServiceProvider extends AbstractServiceProvider $this->app->singleton('flarum.admin.routes', function () { return new RouteCollection; }); + + $this->app->singleton('flarum.admin.middleware', function ($app) { + $pipe = new MiddlewarePipe; + $pipe->raiseThrowables(); + + // All requests should first be piped through our global error handler + $debugMode = ! $app->isUpToDate() || $app->inDebugMode(); + $errorDir = __DIR__.'/../../error'; + $pipe->pipe(new HandleErrors($errorDir, $app->make('log'), $debugMode)); + + $pipe->pipe($app->make(ParseJsonBody::class)); + $pipe->pipe($app->make(StartSession::class)); + $pipe->pipe($app->make(RememberFromCookie::class)); + $pipe->pipe($app->make(AuthenticateWithSession::class)); + $pipe->pipe($app->make(SetLocale::class)); + $pipe->pipe($app->make(RequireAdministrateAbility::class)); + + event(new ConfigureMiddleware($pipe, 'admin')); + + $pipe->pipe($app->make(DispatchRoute::class, ['routes' => $app->make('flarum.admin.routes')])); + + return $pipe; + }); } /** diff --git a/src/Admin/Server.php b/src/Admin/Server.php deleted file mode 100644 index 43aa38116..000000000 --- a/src/Admin/Server.php +++ /dev/null @@ -1,58 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Flarum\Admin; - -use Flarum\Event\ConfigureMiddleware; -use Flarum\Foundation\Application; -use Flarum\Http\AbstractServer; -use Flarum\Http\Middleware\HandleErrors; -use Zend\Stratigility\MiddlewarePipe; - -class Server extends AbstractServer -{ - /** - * {@inheritdoc} - */ - protected function getMiddleware(Application $app) - { - $pipe = new MiddlewarePipe; - $pipe->raiseThrowables(); - - if ($app->isInstalled()) { - $path = parse_url($app->url('admin'), PHP_URL_PATH); - $errorDir = __DIR__.'/../../error'; - - // All requests should first be piped through our global error handler - $debugMode = ! $app->isUpToDate() || $app->inDebugMode(); - $pipe->pipe($path, new HandleErrors($errorDir, $app->make('log'), $debugMode)); - - if ($app->isUpToDate()) { - $pipe->pipe($path, $app->make('Flarum\Http\Middleware\ParseJsonBody')); - $pipe->pipe($path, $app->make('Flarum\Http\Middleware\StartSession')); - $pipe->pipe($path, $app->make('Flarum\Http\Middleware\RememberFromCookie')); - $pipe->pipe($path, $app->make('Flarum\Http\Middleware\AuthenticateWithSession')); - $pipe->pipe($path, $app->make('Flarum\Http\Middleware\SetLocale')); - $pipe->pipe($path, $app->make('Flarum\Admin\Middleware\RequireAdministrateAbility')); - - event(new ConfigureMiddleware($pipe, $path, $this)); - - $pipe->pipe($path, $app->make('Flarum\Http\Middleware\DispatchRoute', ['routes' => $app->make('flarum.admin.routes')])); - } else { - $app->register('Flarum\Update\UpdateServiceProvider'); - - $pipe->pipe($path, $app->make('Flarum\Http\Middleware\DispatchRoute', ['routes' => $app->make('flarum.update.routes')])); - } - } - - return $pipe; - } -} diff --git a/src/Api/ApiServiceProvider.php b/src/Api/ApiServiceProvider.php index ed4f916f3..7360358a3 100644 --- a/src/Api/ApiServiceProvider.php +++ b/src/Api/ApiServiceProvider.php @@ -12,17 +12,28 @@ namespace Flarum\Api; use Flarum\Api\Controller\AbstractSerializeController; +use Flarum\Api\Middleware\FakeHttpMethods; +use Flarum\Api\Middleware\HandleErrors; use Flarum\Api\Serializer\AbstractSerializer; use Flarum\Api\Serializer\NotificationSerializer; use Flarum\Event\ConfigureApiRoutes; +use Flarum\Event\ConfigureMiddleware; use Flarum\Event\ConfigureNotificationTypes; use Flarum\Foundation\AbstractServiceProvider; +use Flarum\Http\Middleware\AuthenticateWithHeader; +use Flarum\Http\Middleware\AuthenticateWithSession; +use Flarum\Http\Middleware\DispatchRoute; +use Flarum\Http\Middleware\ParseJsonBody; +use Flarum\Http\Middleware\RememberFromCookie; +use Flarum\Http\Middleware\SetLocale; +use Flarum\Http\Middleware\StartSession; use Flarum\Http\RouteCollection; use Flarum\Http\RouteHandlerFactory; use Flarum\Http\UrlGenerator; use Tobscure\JsonApi\ErrorHandler; use Tobscure\JsonApi\Exception\Handler\FallbackExceptionHandler; use Tobscure\JsonApi\Exception\Handler\InvalidParameterExceptionHandler; +use Zend\Stratigility\MiddlewarePipe; class ApiServiceProvider extends AbstractServiceProvider { @@ -39,6 +50,27 @@ class ApiServiceProvider extends AbstractServiceProvider return new RouteCollection; }); + $this->app->singleton('flarum.api.middleware', function ($app) { + $pipe = new MiddlewarePipe; + $pipe->raiseThrowables(); + + $pipe->pipe($app->make(HandleErrors::class)); + + $pipe->pipe($app->make(ParseJsonBody::class)); + $pipe->pipe($app->make(FakeHttpMethods::class)); + $pipe->pipe($app->make(StartSession::class)); + $pipe->pipe($app->make(RememberFromCookie::class)); + $pipe->pipe($app->make(AuthenticateWithSession::class)); + $pipe->pipe($app->make(AuthenticateWithHeader::class)); + $pipe->pipe($app->make(SetLocale::class)); + + event(new ConfigureMiddleware($pipe, 'api')); + + $pipe->pipe($app->make(DispatchRoute::class, ['routes' => $app->make('flarum.api.routes')])); + + return $pipe; + }); + $this->app->singleton(ErrorHandler::class, function () { $handler = new ErrorHandler; diff --git a/src/Api/Server.php b/src/Api/Server.php deleted file mode 100644 index 79dbb03b6..000000000 --- a/src/Api/Server.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Flarum\Api; - -use Flarum\Event\ConfigureMiddleware; -use Flarum\Foundation\Application; -use Flarum\Http\AbstractServer; -use Tobscure\JsonApi\Document; -use Zend\Stratigility\MiddlewarePipe; - -class Server extends AbstractServer -{ - /** - * {@inheritdoc} - */ - protected function getMiddleware(Application $app) - { - $pipe = new MiddlewarePipe; - $pipe->raiseThrowables(); - - $path = parse_url($app->url('api'), PHP_URL_PATH); - - if ($app->isInstalled() && $app->isUpToDate()) { - $pipe->pipe($path, $app->make('Flarum\Api\Middleware\HandleErrors')); - - $pipe->pipe($path, $app->make('Flarum\Http\Middleware\ParseJsonBody')); - $pipe->pipe($path, $app->make('Flarum\Api\Middleware\FakeHttpMethods')); - $pipe->pipe($path, $app->make('Flarum\Http\Middleware\StartSession')); - $pipe->pipe($path, $app->make('Flarum\Http\Middleware\RememberFromCookie')); - $pipe->pipe($path, $app->make('Flarum\Http\Middleware\AuthenticateWithSession')); - $pipe->pipe($path, $app->make('Flarum\Http\Middleware\AuthenticateWithHeader')); - $pipe->pipe($path, $app->make('Flarum\Http\Middleware\SetLocale')); - - event(new ConfigureMiddleware($pipe, $path, $this)); - - $pipe->pipe($path, $app->make('Flarum\Http\Middleware\DispatchRoute', ['routes' => $app->make('flarum.api.routes')])); - } else { - $pipe->pipe($path, function () { - $document = new Document; - $document->setErrors([ - [ - 'code' => 503, - 'title' => 'Service Unavailable' - ] - ]); - - return new JsonApiResponse($document, 503); - }); - } - - return $pipe; - } -} diff --git a/src/Event/ConfigureMiddleware.php b/src/Event/ConfigureMiddleware.php index 80ebb649f..e602d5532 100644 --- a/src/Event/ConfigureMiddleware.php +++ b/src/Event/ConfigureMiddleware.php @@ -11,10 +11,6 @@ namespace Flarum\Event; -use Flarum\Admin\Server as AdminServer; -use Flarum\Api\Server as ApiServer; -use Flarum\Forum\Server as ForumServer; -use Flarum\Foundation\AbstractServer; use Zend\Stratigility\MiddlewarePipe; class ConfigureMiddleware @@ -27,42 +23,35 @@ class ConfigureMiddleware /** * @var string */ - public $path; - - /** - * @var AbstractServer - */ - public $server; + public $stackName; /** * @param MiddlewarePipe $pipe - * @param string $path - * @param AbstractServer $server + * @param string $stackName */ - public function __construct(MiddlewarePipe $pipe, $path, AbstractServer $server) + public function __construct(MiddlewarePipe $pipe, $stackName) { $this->pipe = $pipe; - $this->path = $path; - $this->server = $server; + $this->stackName = $stackName; } public function pipe(callable $middleware) { - $this->pipe->pipe($this->path, $middleware); + $this->pipe->pipe($middleware); } public function isForum() { - return $this->server instanceof ForumServer; + return $this->stackName === 'forum'; } public function isAdmin() { - return $this->server instanceof AdminServer; + return $this->stackName === 'admin'; } public function isApi() { - return $this->server instanceof ApiServer; + return $this->stackName === 'api'; } } diff --git a/src/Forum/ForumServiceProvider.php b/src/Forum/ForumServiceProvider.php index 682d8194b..1e2e058b4 100644 --- a/src/Forum/ForumServiceProvider.php +++ b/src/Forum/ForumServiceProvider.php @@ -12,13 +12,22 @@ namespace Flarum\Forum; use Flarum\Event\ConfigureForumRoutes; +use Flarum\Event\ConfigureMiddleware; use Flarum\Extension\Event\Disabled; use Flarum\Extension\Event\Enabled; use Flarum\Foundation\AbstractServiceProvider; +use Flarum\Http\Middleware\AuthenticateWithSession; +use Flarum\Http\Middleware\DispatchRoute; +use Flarum\Http\Middleware\HandleErrors; +use Flarum\Http\Middleware\ParseJsonBody; +use Flarum\Http\Middleware\RememberFromCookie; +use Flarum\Http\Middleware\SetLocale; +use Flarum\Http\Middleware\StartSession; use Flarum\Http\RouteCollection; use Flarum\Http\RouteHandlerFactory; use Flarum\Http\UrlGenerator; use Flarum\Settings\Event\Saved; +use Zend\Stratigility\MiddlewarePipe; class ForumServiceProvider extends AbstractServiceProvider { @@ -34,6 +43,28 @@ class ForumServiceProvider extends AbstractServiceProvider $this->app->singleton('flarum.forum.routes', function () { return new RouteCollection; }); + + $this->app->singleton('flarum.forum.middleware', function ($app) { + $pipe = new MiddlewarePipe; + $pipe->raiseThrowables(); + + // All requests should first be piped through our global error handler + $debugMode = ! $app->isUpToDate() || $app->inDebugMode(); + $errorDir = __DIR__.'/../../error'; + $pipe->pipe(new HandleErrors($errorDir, $app->make('log'), $debugMode)); + + $pipe->pipe($app->make(ParseJsonBody::class)); + $pipe->pipe($app->make(StartSession::class)); + $pipe->pipe($app->make(RememberFromCookie::class)); + $pipe->pipe($app->make(AuthenticateWithSession::class)); + $pipe->pipe($app->make(SetLocale::class)); + + event(new ConfigureMiddleware($pipe, 'forum')); + + $pipe->pipe($app->make(DispatchRoute::class, ['routes' => $app->make('flarum.forum.routes')])); + + return $pipe; + }); } /** diff --git a/src/Forum/Server.php b/src/Forum/Server.php deleted file mode 100644 index 893ddc52c..000000000 --- a/src/Forum/Server.php +++ /dev/null @@ -1,61 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Flarum\Forum; - -use Flarum\Event\ConfigureMiddleware; -use Flarum\Foundation\Application; -use Flarum\Http\AbstractServer; -use Flarum\Http\Middleware\HandleErrors; -use Zend\Diactoros\Response\HtmlResponse; -use Zend\Stratigility\MiddlewarePipe; - -class Server extends AbstractServer -{ - /** - * {@inheritdoc} - */ - protected function getMiddleware(Application $app) - { - $pipe = new MiddlewarePipe; - $pipe->raiseThrowables(); - - $path = parse_url($app->url(), PHP_URL_PATH); - $errorDir = __DIR__.'/../../error'; - - if (! $app->isInstalled()) { - $app->register('Flarum\Install\InstallServiceProvider'); - - $pipe->pipe($path, new HandleErrors($errorDir, $app->make('log'), true)); - - $pipe->pipe($path, $app->make('Flarum\Http\Middleware\StartSession')); - $pipe->pipe($path, $app->make('Flarum\Http\Middleware\DispatchRoute', ['routes' => $app->make('flarum.install.routes')])); - } elseif ($app->isUpToDate() && ! $app->isDownForMaintenance()) { - $pipe->pipe($path, new HandleErrors($errorDir, $app->make('log'), $app->inDebugMode())); - - $pipe->pipe($path, $app->make('Flarum\Http\Middleware\ParseJsonBody')); - $pipe->pipe($path, $app->make('Flarum\Http\Middleware\StartSession')); - $pipe->pipe($path, $app->make('Flarum\Http\Middleware\RememberFromCookie')); - $pipe->pipe($path, $app->make('Flarum\Http\Middleware\AuthenticateWithSession')); - $pipe->pipe($path, $app->make('Flarum\Http\Middleware\SetLocale')); - - event(new ConfigureMiddleware($pipe, $path, $this)); - - $pipe->pipe($path, $app->make('Flarum\Http\Middleware\DispatchRoute', ['routes' => $app->make('flarum.forum.routes')])); - } else { - $pipe->pipe($path, function () use ($errorDir) { - return new HtmlResponse(file_get_contents($errorDir.'/503.html', 503)); - }); - } - - return $pipe; - } -} diff --git a/src/Http/AbstractServer.php b/src/Http/AbstractServer.php deleted file mode 100644 index 0cf7bd39d..000000000 --- a/src/Http/AbstractServer.php +++ /dev/null @@ -1,81 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Flarum\Http; - -use Flarum\Foundation\AbstractServer as BaseAbstractServer; -use Flarum\Foundation\Application; -use Flarum\User\AuthToken; -use Flarum\User\EmailToken; -use Flarum\User\PasswordToken; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; -use Zend\Diactoros\Server; -use Zend\Stratigility\MiddlewareInterface; -use Zend\Stratigility\NoopFinalHandler; - -abstract class AbstractServer extends BaseAbstractServer -{ - public function listen() - { - Server::createServer( - $this, - $_SERVER, - $_GET, - $_POST, - $_COOKIE, - $_FILES - )->listen(new NoopFinalHandler()); - } - - /** - * Use as PSR-7 middleware. - * - * @param ServerRequestInterface $request - * @param ResponseInterface $response - * @param callable $out - * @return ResponseInterface - */ - public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $out) - { - $app = $this->getApp(); - - $this->collectGarbage($app); - - $middleware = $this->getMiddleware($app); - - return $middleware($request, $response, $out); - } - - /** - * @param Application $app - * @return MiddlewareInterface - */ - abstract protected function getMiddleware(Application $app); - - private function collectGarbage() - { - if ($this->hitsLottery()) { - AccessToken::whereRaw('last_activity <= ? - lifetime', [time()])->delete(); - - $earliestToKeep = date('Y-m-d H:i:s', time() - 24 * 60 * 60); - - EmailToken::where('created_at', '<=', $earliestToKeep)->delete(); - PasswordToken::where('created_at', '<=', $earliestToKeep)->delete(); - AuthToken::where('created_at', '<=', $earliestToKeep)->delete(); - } - } - - private function hitsLottery() - { - return mt_rand(1, 100) <= 2; - } -} diff --git a/src/Http/FullStackServer.php b/src/Http/FullStackServer.php deleted file mode 100644 index 70b331aba..000000000 --- a/src/Http/FullStackServer.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Flarum\Http; - -use Flarum\Admin\Server as AdminServer; -use Flarum\Api\Server as ApiServer; -use Flarum\Forum\Server as ForumServer; -use Flarum\Foundation\Application; -use Zend\Stratigility\MiddlewarePipe; - -class FullStackServer extends AbstractServer -{ - /** - * @param Application $app - * @return \Zend\Stratigility\MiddlewareInterface - */ - protected function getMiddleware(Application $app) - { - $pipe = new MiddlewarePipe; - $pipe->raiseThrowables(); - - $pipe->pipe(new ApiServer); - $pipe->pipe(new AdminServer); - $pipe->pipe(new ForumServer); - - return $pipe; - } -} diff --git a/src/Http/Server.php b/src/Http/Server.php new file mode 100644 index 000000000..832b58dce --- /dev/null +++ b/src/Http/Server.php @@ -0,0 +1,159 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Http; + +use Flarum\Foundation\AbstractServer; +use Flarum\Foundation\Application; +use Flarum\Http\Middleware\DispatchRoute; +use Flarum\Http\Middleware\HandleErrors; +use Flarum\Http\Middleware\StartSession; +use Flarum\Install\InstallServiceProvider; +use Flarum\Update\UpdateServiceProvider; +use Flarum\User\AuthToken; +use Flarum\User\EmailToken; +use Flarum\User\PasswordToken; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use Zend\Diactoros\Response\HtmlResponse; +use Zend\Diactoros\Server as DiactorosServer; +use Zend\Stratigility\MiddlewareInterface; +use Zend\Stratigility\MiddlewarePipe; +use Zend\Stratigility\NoopFinalHandler; + +class Server extends AbstractServer +{ + public function listen() + { + DiactorosServer::createServer( + $this, + $_SERVER, + $_GET, + $_POST, + $_COOKIE, + $_FILES + )->listen(new NoopFinalHandler()); + } + + /** + * Use as PSR-7 middleware. + * + * @param ServerRequestInterface $request + * @param ResponseInterface $response + * @param callable $out + * @return ResponseInterface + */ + public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $out) + { + $app = $this->getApp(); + + $this->collectGarbage($app); + + $middleware = $this->getMiddleware($app, $request->getUri()->getPath()); + + return $middleware($request, $response, $out); + } + + /** + * @param Application $app + * @param string $requestPath + * @return MiddlewareInterface + */ + protected function getMiddleware(Application $app, $requestPath) + { + $pipe = new MiddlewarePipe; + $pipe->raiseThrowables(); + + if (! $app->isInstalled()) { + return $this->getInstallerMiddleware($pipe, $app); + } else if ($app->isDownForMaintenance()) { + return $this->getMaintenanceMiddleware($pipe); + } else if (! $app->isUpToDate()) { + return $this->getUpdaterMiddleware($pipe, $app); + } + + $forum = parse_url($app->url(''), PHP_URL_PATH) ?: '/'; + $admin = parse_url($app->url('admin'), PHP_URL_PATH); + $api = parse_url($app->url('api'), PHP_URL_PATH); + + if ($this->pathStartsWith($requestPath, $api)) { + $pipe->pipe($api, $app->make('flarum.api.middleware')); + } else if ($this->pathStartsWith($requestPath, $admin)) { + $pipe->pipe($admin, $app->make('flarum.admin.middleware')); + } else { + $pipe->pipe($forum, $app->make('flarum.forum.middleware')); + } + + return $pipe; + } + + private function pathStartsWith($path, $prefix) + { + return $path === $prefix || starts_with($path, "$prefix/"); + } + + protected function getInstallerMiddleware(MiddlewarePipe $pipe, Application $app) + { + $app->register(InstallServiceProvider::class); + + $pipe->pipe(new HandleErrors($this->getErrorDir(), $app->make('log'), true)); + + $pipe->pipe($app->make(StartSession::class)); + $pipe->pipe($app->make(DispatchRoute::class, ['routes' => $app->make('flarum.install.routes')])); + + return $pipe; + } + + protected function getMaintenanceMiddleware(MiddlewarePipe $pipe) + { + $pipe->pipe(function () { + return new HtmlResponse(file_get_contents($this->getErrorDir().'/503.html', 503)); + }); + + // TODO: FOR API render JSON-API error document for HTTP 503 + + return $pipe; + } + + protected function getUpdaterMiddleware(MiddlewarePipe $pipe, Application $app) + { + $app->register(UpdateServiceProvider::class); + + $pipe->pipe($app->make(DispatchRoute::class, ['routes' => $app->make('flarum.update.routes')])); + + // TODO: FOR API render JSON-API error document for HTTP 503 + + return $pipe; + } + + private function collectGarbage() + { + if ($this->hitsLottery()) { + AccessToken::whereRaw('last_activity <= ? - lifetime', [time()])->delete(); + + $earliestToKeep = date('Y-m-d H:i:s', time() - 24 * 60 * 60); + + EmailToken::where('created_at', '<=', $earliestToKeep)->delete(); + PasswordToken::where('created_at', '<=', $earliestToKeep)->delete(); + AuthToken::where('created_at', '<=', $earliestToKeep)->delete(); + } + } + + private function getErrorDir() + { + return __DIR__.'/../../error'; + } + + private function hitsLottery() + { + return mt_rand(1, 100) <= 2; + } +}