Passed
Push — feature/application-review-ui ( afbf92 )
by Chris
06:55
created

Handler::renderHttpException()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 9
c 0
b 0
f 0
dl 0
loc 13
rs 9.9666
cc 2
nc 2
nop 1
1
<?php
2
3
namespace App\Exceptions;
4
5
use Illuminate\Auth\Access\AuthorizationException;
6
use Illuminate\Auth\AuthenticationException;
7
use Illuminate\Database\Eloquent\ModelNotFoundException;
8
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
9
use Illuminate\Http\Exceptions\HttpResponseException;
10
use Illuminate\Session\TokenMismatchException;
11
use Illuminate\Support\Facades\Lang;
12
use Illuminate\Support\Facades\Log;
13
use Illuminate\Support\Facades\Request;
14
use Illuminate\Support\Facades\Auth;
15
use Illuminate\Validation\ValidationException;
16
use Symfony\Component\HttpKernel\Exception\HttpException;
17
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
18
19
class Handler extends ExceptionHandler
20
{
21
    /**
22
     * A list of the exception types that are not reported.
23
     *
24
     * @var array
25
     */
26
    protected $dontReport = [];
27
28
    /**
29
     * A list of the inputs that are never flashed for validation exceptions.
30
     *
31
     * @var array
32
     */
33
    protected $dontFlash = [
34
        'password',
35
        'password_confirmation',
36
        'current_password',
37
        'new_password',
38
        'new_password_confirmation',
39
    ];
40
41
    /**
42
     * OVERRIDE
43
     * A list of the internal exception types that should not be reported.
44
     *
45
     * @var array
46
     */
47
    protected $internalDontReport = [
48
        AuthenticationException::class,
49
        AuthorizationException::class,
50
        HttpResponseException::class,
51
        ModelNotFoundException::class,
52
        ValidationException::class,
53
    ];
54
55
    /**
56
     * Report or log an exception.
57
     *
58
     * @param  \Exception  $exception
59
     * @return void
60
     */
61
    public function report(\Exception $exception)
62
    {
63
        if ($exception instanceof TokenMismatchException) {
64
            $logData = [
65
                'requestToken' => request()->header('x-csrf-token'),
0 ignored issues
show
Bug introduced by
The function request was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

65
                'requestToken' => /** @scrutinizer ignore-call */ request()->header('x-csrf-token'),
Loading history...
66
                'sessionToken' => session()->token(),
0 ignored issues
show
Bug introduced by
The function session was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

66
                'sessionToken' => /** @scrutinizer ignore-call */ session()->token(),
Loading history...
67
                'session' => session()->all(),
68
                'user' => request()->user(),
69
                'requestUrl' => request()->url()
70
            ];
71
            $message = '419 CSRF Token Mismatch. ' . collect($logData)->toJson();
0 ignored issues
show
Bug introduced by
The function collect was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

71
            $message = '419 CSRF Token Mismatch. ' . /** @scrutinizer ignore-call */ collect($logData)->toJson();
Loading history...
72
            Log::debug($message);
73
        }
74
75
        parent::report($exception);
76
    }
77
78
    /**
79
     * OVERRIDE
80
     * Get the default context variables for logging.
81
     *
82
     * @return array
83
     */
84
    protected function context()
85
    {
86
        try {
87
            return array_filter([
88
                'userId' => Auth::id(),
89
                'url' => Request::path(),
90
                'method' => Request::method(),
91
                'referer' => Request::header('referer', '')
92
            ]);
93
        } catch (\Throwable $e) {
94
            return [];
95
        }
96
    }
97
98
    /**
99
     * Render an exception into an HTTP response.
100
     *
101
     * @param  \Illuminate\Http\Request  $request
102
     * @param  \Exception  $exception
103
     * @return \Illuminate\Http\Response
104
     */
105
    public function render($request, \Exception $exception)
106
    {
107
        // Redirect upper case URLs to lower case route.
108
        $url = $request->url();
109
        $loweredCaseUrl = strtolower($url);
110
        if ($exception instanceof \Symfony\Component\HttpKernel\Exception\NotFoundHttpException && $url !== $loweredCaseUrl) {
111
            return redirect($loweredCaseUrl);
0 ignored issues
show
Bug introduced by
The function redirect was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

111
            return /** @scrutinizer ignore-call */ redirect($loweredCaseUrl);
Loading history...
112
        }
113
114
        // Laravel will render out the error page by default even for JSON
115
        // requests... this will return a standardized JSON response with a 403
116
        // if unauthorized.
117
        if ($exception instanceof AuthorizationException && $request->wantsJson()) {
118
            return response()->json(['message' => $exception->getMessage()], 403);
0 ignored issues
show
Bug introduced by
The function response was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

118
            return /** @scrutinizer ignore-call */ response()->json(['message' => $exception->getMessage()], 403);
Loading history...
119
        }
120
        if ($exception instanceof AdminException) {
121
            return $exception->render($request);
122
        }
123
        if ($exception instanceof TwoFactorRequiredException) {
124
            return $exception->render($request);
125
        }
126
        if ($exception instanceof TokenMismatchException) {
127
            $newMessage = $exception->getMessage() . ' ' . Lang::get('errors.refresh_page');
128
            $modifiedException = new TokenMismatchException($newMessage, $exception->getCode(), $exception);
129
            return parent::render($request, $modifiedException);
130
        }
131
        if ($exception instanceof StateMachineException) {
132
            return parent::render($request, new HttpException(400, $exception->getMessage()));
133
        }
134
        if ($exception instanceof SendEmailException) {
135
            return parent::render($request, new HttpException(400, $exception->getMessage()));
136
        }
137
        return parent::render($request, $exception);
138
    }
139
140
    /**
141
     * Convert an authentication exception into an unauthenticated response.
142
     *
143
     * @param  \Illuminate\Http\Request  $request
144
     * @param  \Illuminate\Auth\AuthenticationException  $exception
145
     * @return \Illuminate\Http\Response
146
     */
147
    protected function unauthenticated($request, AuthenticationException $exception)
148
    {
149
        if ($request->expectsJson()) {
150
            return response()->json(['error' => 'Unauthenticated.'], 401);
0 ignored issues
show
Bug introduced by
The function response was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

150
            return /** @scrutinizer ignore-call */ response()->json(['error' => 'Unauthenticated.'], 401);
Loading history...
151
        }
152
        $loginRoute = ($exception->redirectTo() !== null && $exception->redirectTo() !== '')
153
            ? $exception->redirectTo()
154
            : route('login');
0 ignored issues
show
Bug introduced by
The function route was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

154
            : /** @scrutinizer ignore-call */ route('login');
Loading history...
155
        return redirect()->guest($loginRoute);
0 ignored issues
show
Bug introduced by
The function redirect was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

155
        return /** @scrutinizer ignore-call */ redirect()->guest($loginRoute);
Loading history...
156
    }
157
158
    /**
159
     * OVERRIDE
160
     * Render the given HttpException.
161
     *
162
     * @param  \Symfony\Component\HttpKernel\Exception\HttpExceptionInterface  $e
163
     * @return \Symfony\Component\HttpFoundation\Response
164
     */
165
    protected function renderHttpException(HttpExceptionInterface $e)
166
    {
167
        if (!view()->exists("errors.{$e->getStatusCode()}")) {
0 ignored issues
show
Bug introduced by
The function view was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

167
        if (!/** @scrutinizer ignore-call */ view()->exists("errors.{$e->getStatusCode()}")) {
Loading history...
168
            return response()->view('errors.default', [
0 ignored issues
show
Bug introduced by
The function response was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

168
            return /** @scrutinizer ignore-call */ response()->view('errors.default', [
Loading history...
169
                'exception' => $e,
170
                'goc' => Lang::get('common/goc'),
171
                'alert' => Lang::get('common/alert'),
172
                'error' => [
173
                    'title' => 'Error'
174
                ]
175
            ], $e->getStatusCode(), $e->getHeaders());
176
        }
177
        return parent::renderHttpException($e);
178
    }
179
}
180