Passed
Pull Request — master (#4)
by Adam
01:51
created

UrlGenerator::hasValidParameterSignature()   B

Complexity

Conditions 8
Paths 6

Size

Total Lines 26
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 11
dl 0
loc 26
rs 8.4444
c 0
b 0
f 0
cc 8
nc 6
nop 2
1
<?php
2
3
namespace Endeavors\Components\Routing;
4
5
use Illuminate\Contracts\Routing\UrlGenerator as UrlGeneratorContract;
6
use DateInterval;
7
use DateTimeInterface;
8
use Carbon\Carbon;
9
use Illuminate\Http\Request;
10
use Illuminate\Routing\RouteCollection;
11
12
/**
13
 * Decorate the UrlGenerator for simplicity
14
 */
15
class UrlGenerator implements UrlGeneratorContract, IEnableRoutes
16
{
17
    private $originalUrlGenerator;
18
19
    public function __construct(UrlGeneratorContract $originalUrlGenerator)
20
    {
21
        $this->originalUrlGenerator = $originalUrlGenerator;
22
    }
23
24
    /**
25
     * Get the full URL for the current request.
26
     *
27
     * @return string
28
     */
29
    public function full()
30
    {
31
        return $this->originalUrlGenerator->full();
32
    }
33
34
    /**
35
     * Get the current URL for the request.
36
     *
37
     * @return string
38
     */
39
    public function current()
40
    {
41
        return $this->originalUrlGenerator->current();
42
    }
43
44
    /**
45
     * Get the URL for the previous request.
46
     *
47
     * @return string
48
     */
49
    public function previous($fallback = false)
50
    {
51
        return $this->originalUrlGenerator->previous($fallback);
52
    }
53
54
    /**
55
     * Generate a absolute URL to the given path.
56
     *
57
     * @param  string  $path
58
     * @param  mixed  $extra
59
     * @param  bool|null  $secure
60
     * @return string
61
     */
62
    public function to($path, $extra = array(), $secure = null)
63
    {
64
        return $this->originalUrlGenerator->to($path, $extra, $secure);
65
    }
66
67
    /**
68
     * Generate a secure, absolute URL to the given path.
69
     *
70
     * @param  string  $path
71
     * @param  array   $parameters
72
     * @return string
73
     */
74
    public function secure($path, $parameters = array())
75
    {
76
        return $this->originalUrlGenerator->secure($path, $parameters);
77
    }
78
79
    /**
80
     * Generate a URL to an application asset.
81
     *
82
     * @param  string  $path
83
     * @param  bool|null  $secure
84
     * @return string
85
     */
86
    public function asset($path, $secure = null)
87
    {
88
        return $this->originalUrlGenerator->asset($path, $secure);
89
    }
90
91
    /**
92
     * Generate a URL to a secure asset.
93
     *
94
     * @param  string  $path
95
     * @return string
96
     */
97
    public function secureAsset($path)
98
    {
99
        return $this->originalUrlGenerator->secureAsset($path);
100
    }
101
102
    /**
103
     * Force the schema for URLs.
104
     *
105
     * @param  string  $schema
106
     * @return void
107
     */
108
    public function forceSchema($schema)
109
    {
110
        $this->originalUrlGenerator->forceSchema($schema);
111
    }
112
113
    /**
114
     * Get the URL to a named route.
115
     *
116
     * @param  string  $name
117
     * @param  mixed   $parameters
118
     * @param  bool  $absolute
119
     * @param  \Illuminate\Routing\Route  $route
120
     * @return string
121
     *
122
     * @throws \InvalidArgumentException
123
     */
124
    public function route($name, $parameters = array(), $absolute = true, $route = null)
125
    {
126
        return $this->originalUrlGenerator->route($name, $parameters, $absolute, $route);
127
    }
128
129
    /**
130
     * Get the URL to a controller action.
131
     *
132
     * @param  string  $action
133
     * @param  mixed   $parameters
134
     * @param  bool    $absolute
135
     * @return string
136
     */
137
    public function action($action, $parameters = array(), $absolute = true)
138
    {
139
        return $this->originalUrlGenerator->action($action, $parameters, $absolute);
140
    }
141
142
    /**
143
     * Set the forced root URL.
144
     *
145
     * @param  string  $root
146
     * @return void
147
     */
148
    public function forceRootUrl($root)
149
    {
150
        $this->originalUrlGenerator->forceRootUrl($root);
151
    }
152
153
    /**
154
     * Determine if the given path is a valid URL.
155
     *
156
     * @param  string  $path
157
     * @return bool
158
     */
159
    public function isValidUrl($path)
160
    {
161
        return $this->originalUrlGenerator->isValidUrl($path);
162
    }
163
164
    /**
165
     * Get the request instance.
166
     *
167
     * @return \Symfony\Component\HttpFoundation\Request
168
     */
169
    public function getRequest()
170
    {
171
        return $this->originalUrlGenerator->getRequest();
172
    }
173
174
    /**
175
     * Set the current request instance.
176
     *
177
     * @param  \Illuminate\Http\Request  $request
178
     * @return void
179
     */
180
    public function setRequest(Request $request)
181
    {
182
        $this->originalUrlGenerator->setRequest($request);
183
    }
184
185
    public function setRoutes(RouteCollection $routes)
186
    {
187
        return $this->originalUrlGenerator->setRoutes($routes);
188
    }
189
190
    public function setSessionResolver(callable $sessionResolver)
191
    {
192
        return $this->originalUrlGenerator->setSessionResolver($sessionResolver);
193
    }
194
195
    public function setRootControllerNamespace($rootNamespace)
196
    {
197
        return $this->originalUrlGenerator->setRootControllerNamespace($rootNamespace);
198
    }
199
200
    public function getOriginalUrlGenerator()
201
    {
202
        return $this->originalUrlGenerator;
203
    }
204
205
    /**
206
     * @return bool
207
     */
208
    public function hasValidSignature(Request $request)
209
    {
210
        $original = rtrim($request->url().'?'.http_build_query(
211
            Arr::except($request->query(), 'signature')
212
        ), '?');
213
214
        $expires = Arr::get($request->query(), 'expires');
215
        $signature = hash_hmac('sha256', $original, call_user_func($this->keyResolver));
216
        return  hash_equals($signature, $request->query('signature', '')) && !($expires && Carbon::now()->getTimestamp() > $expires);
217
    }
218
    
219
    /**
220
     * Only check validity of signature if specified parameters exist
221
     */
222
    public function hasValidParameterSignature(Request $request, array $parameters = [])
223
    {
224
        // we'll bail here as we need at least one
225
        if (count($parameters) === 0) {
226
            return true;
227
        } 
228
229
        foreach($parameters as $parameter) {
230
            // if the request has the parameter or
231
            // the route has the parameter we check the signature
232
            if ($request->has($parameter)) { 
233
                return $this->hasValidSignature($request); 
234
            }
235
236
            $route = $request->route($parameter);
237
238
            if($route instanceof \Illuminate\Routing\Route && $route->hasParameter($parameter)) {
239
                return $this->hasValidSignature($request);
240
            }
241
242
            if (is_string($route) && strlen($route) > 0) {
243
                return $this->hasValidSignature($request);
244
            }
245
        }
246
247
        return true;
248
    }
249
250
    /**
251
     * Create a signed route URL for a named route.
252
     *
253
     * @param  string  $name
254
     * @param  array  $parameters
255
     * @param  \DateTimeInterface|int  $expiration
256
     * @return string
257
     */
258
    public function signedRoute($name, $parameters = [], $expiration = null)
259
    {
260
        $parameters = $this->formatParameters($parameters);
261
        if ($expiration) {
262
            $parameters = $parameters + ['expires' => $this->availableAt($expiration)];
263
        }
264
        ksort($parameters);
265
        $key = call_user_func($this->keyResolver);
266
        return $this->route($name, $parameters + [
267
            'signature' => hash_hmac('sha256', $this->route($name, $parameters), $key),
268
        ]);
269
    }
270
    /**
271
     * Create a temporary signed route URL for a named route.
272
     *
273
     * @param  string  $name
274
     * @param  \DateTimeInterface|int  $expiration
275
     * @param  array  $parameters
276
     * @return string
277
     */
278
    public function temporarySignedRoute($name, $expiration, $parameters = [])
279
    {
280
        return $this->signedRoute($name, $parameters, $expiration);
281
    }
282
283
    /**
284
     * Format the array of URL parameters.
285
     *
286
     * @param  mixed|array  $parameters
287
     * @return array
288
     */
289
    public function formatParameters($parameters)
290
    {
291
        $parameters = Arr::wrap($parameters);
292
        foreach ($parameters as $key => $parameter) {
293
            if ($parameter instanceof UrlRoutable) {
0 ignored issues
show
Bug introduced by
The type Endeavors\Components\Routing\UrlRoutable was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
294
                $parameters[$key] = $parameter->getRouteKey();
295
            }
296
        }
297
        return $parameters;
298
    }
299
300
    /**
301
     * Get the "available at" UNIX timestamp.
302
     *
303
     * @param  \DateTimeInterface|\DateInterval|int  $delay
304
     * @return int
305
     */
306
    protected function availableAt($delay = 0)
307
    {
308
        $delay = $this->parseDateInterval($delay);
309
        return $delay instanceof DateTimeInterface
0 ignored issues
show
introduced by
$delay is always a sub-type of DateTimeInterface.
Loading history...
310
                            ? $delay->getTimestamp()
311
                            : Carbon::now()->addSeconds($delay)->getTimestamp();
312
    }
313
314
    /**
315
     * If the given value is an interval, convert it to a DateTime instance.
316
     *
317
     * @param  \DateTimeInterface|\DateInterval|int  $delay
318
     * @return \DateTimeInterface|int
319
     */
320
    protected function parseDateInterval($delay)
321
    {
322
        if ($delay instanceof DateInterval) {
323
            $delay = Carbon::now()->add($delay);
324
        }
325
        return $delay;
326
    }
327
328
    /**
329
     * The encryption key resolver callable.
330
     *
331
     * @var callable
332
     */
333
    protected $keyResolver;
334
335
    /**
336
     * Set the encryption key resolver.
337
     *
338
     * @param  callable  $keyResolver
339
     * @return $this
340
     */
341
    public function setKeyResolver(callable $keyResolver)
342
    {
343
        $this->keyResolver = $keyResolver;
344
        return $this;
345
    }
346
}
347