3 namespace BookStack\Exceptions;
6 use Illuminate\Auth\AuthenticationException;
7 use Illuminate\Http\Request;
8 use Illuminate\Pipeline\Pipeline;
9 use Illuminate\Validation\ValidationException;
10 use Illuminate\Database\Eloquent\ModelNotFoundException;
11 use Symfony\Component\HttpKernel\Exception\HttpException;
12 use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
13 use Illuminate\Auth\Access\AuthorizationException;
14 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
16 class Handler extends ExceptionHandler
19 * A list of the exception types that should not be reported.
23 protected $dontReport = [
24 AuthorizationException::class,
26 ModelNotFoundException::class,
27 ValidationException::class,
31 * Report or log an exception.
32 * This is a great spot to send exceptions to Sentry, Bugsnag, etc.
34 * @param \Exception $e
37 public function report(Exception $e)
39 return parent::report($e);
43 * Render an exception into an HTTP response.
45 * @param \Illuminate\Http\Request $request
46 * @param \Exception $e
47 * @return \Illuminate\Http\Response
49 public function render($request, Exception $e)
51 // Handle notify exceptions which will redirect to the
52 // specified location then show a notification message.
53 if ($this->isExceptionType($e, NotifyException::class)) {
54 session()->flash('error', $this->getOriginalMessage($e));
55 return redirect($e->redirectLocation);
58 // Handle pretty exceptions which will show a friendly application-fitting page
59 // Which will include the basic message to point the user roughly to the cause.
60 if ($this->isExceptionType($e, PrettyException::class) && !config('app.debug')) {
61 $message = $this->getOriginalMessage($e);
62 $code = ($e->getCode() === 0) ? 500 : $e->getCode();
63 return response()->view('errors/' . $code, ['message' => $message], $code);
66 // Handle 404 errors with a loaded session to enable showing user-specific information
67 if ($this->isExceptionType($e, NotFoundHttpException::class)) {
68 return $this->loadErrorMiddleware($request, function ($request) use ($e) {
69 $message = $e->getMessage() ?: trans('errors.404_page_not_found');
70 return response()->view('errors/404', ['message' => $message], 404);
74 return parent::render($request, $e);
78 * Load the middleware required to show state/session-enabled error pages.
79 * @param Request $request
83 protected function loadErrorMiddleware(Request $request, $callback)
85 $middleware = (\Route::getMiddlewareGroups()['web_errors']);
86 return (new Pipeline($this->container))
88 ->through($middleware)
93 * Check the exception chain to compare against the original exception type.
98 protected function isExceptionType(Exception $e, $type)
101 if (is_a($e, $type)) {
104 } while ($e = $e->getPrevious());
109 * Get original exception message.
110 * @param Exception $e
113 protected function getOriginalMessage(Exception $e)
116 $message = $e->getMessage();
117 } while ($e = $e->getPrevious());
122 * Convert an authentication exception into an unauthenticated response.
124 * @param \Illuminate\Http\Request $request
125 * @param \Illuminate\Auth\AuthenticationException $exception
126 * @return \Illuminate\Http\Response
128 protected function unauthenticated($request, AuthenticationException $exception)
130 if ($request->expectsJson()) {
131 return response()->json(['error' => 'Unauthenticated.'], 401);
134 return redirect()->guest('login');
138 * Convert a validation exception into a JSON response.
140 * @param \Illuminate\Http\Request $request
141 * @param \Illuminate\Validation\ValidationException $exception
142 * @return \Illuminate\Http\JsonResponse
144 protected function invalidJson($request, ValidationException $exception)
146 return response()->json($exception->errors(), $exception->status);