2022-07-26 10:38:32 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Lib;
|
|
|
|
|
|
|
|
|
|
use App\Exceptions\Api\DamException;
|
|
|
|
|
use Illuminate\Contracts\Encryption\DecryptException;
|
|
|
|
|
use Illuminate\Http\Request;
|
|
|
|
|
use Illuminate\Support\Arr;
|
|
|
|
|
use Illuminate\Support\Facades\Crypt;
|
|
|
|
|
use Illuminate\Support\Facades\Route;
|
|
|
|
|
use Illuminate\Support\Str;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Helper Class
|
|
|
|
|
*/
|
|
|
|
|
class Helper
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* Package infos
|
|
|
|
|
*
|
|
|
|
|
* @var array
|
|
|
|
|
*/
|
|
|
|
|
private static $packageInfos;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Tells if the request is within api routes
|
|
|
|
|
*
|
|
|
|
|
* @param Request $request
|
|
|
|
|
* @return boolean
|
|
|
|
|
*/
|
|
|
|
|
public static function isRequestForApi(Request $request): bool
|
|
|
|
|
{
|
|
|
|
|
// * Small hack to ensure to know if route is From APIv1.
|
|
|
|
|
$routePrefix = (strpos(static::getRoutePrefix($request), 'api/') ? 'api/' : null) ??
|
|
|
|
|
(strpos($request->path(), 'api/') === 0 ? 'api/' : null) ?? 'none';
|
|
|
|
|
return strpos($routePrefix, 'api/') === 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Try to get current route name
|
|
|
|
|
*
|
|
|
|
|
* @param Request $request
|
|
|
|
|
* @return string|null
|
|
|
|
|
*/
|
|
|
|
|
public static function getRouteName(Request $request)
|
|
|
|
|
{
|
|
|
|
|
return Route::currentRouteName() ?? ($request->route() ? $request->route()->getName() : null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the bearer token from request
|
|
|
|
|
*
|
|
|
|
|
* @param Request $request
|
|
|
|
|
* @return string|null
|
|
|
|
|
*/
|
|
|
|
|
public static function getBearerTokenFromRequest(Request $request): ?string
|
|
|
|
|
{
|
|
|
|
|
$header = $request->header('Authorization', '');
|
|
|
|
|
|
|
|
|
|
if (Str::contains($header, 'Bearer ')) {
|
|
|
|
|
$auths = \explode(',', $header);
|
|
|
|
|
foreach ($auths as $auth) {
|
|
|
|
|
if (Str::contains($auth, 'Bearer ')) {
|
|
|
|
|
return Str::substr($auth, 7);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Try to get current route prefix
|
|
|
|
|
*
|
|
|
|
|
* @param Request $request
|
|
|
|
|
* @return string|null
|
|
|
|
|
*/
|
|
|
|
|
public static function getRoutePrefix(Request $request)
|
|
|
|
|
{
|
|
|
|
|
return (Route::getCurrentRoute() ? Route::getCurrentRoute()->getPrefix() : null) ??
|
|
|
|
|
($request->route() ? $request->route()->getPrefix() : null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Try to get route from request
|
|
|
|
|
*
|
|
|
|
|
* @param Request $request
|
|
|
|
|
* @return \Illuminate\Routing\Route|null
|
|
|
|
|
*/
|
|
|
|
|
public static function getRoute(Request $request)
|
|
|
|
|
{
|
|
|
|
|
return Route::getRoutes()->getByName(static::getRouteName($request));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get composer.json infos
|
|
|
|
|
*
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
|
|
|
|
public static function getPackageInfo(): array
|
|
|
|
|
{
|
|
|
|
|
if (!static::$packageInfos) {
|
|
|
|
|
static::$packageInfos = \json_decode(\file_get_contents(__DIR__ . '/../../composer.json'), true);
|
|
|
|
|
}
|
|
|
|
|
return static::$packageInfos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Calculate the request signature
|
|
|
|
|
*
|
|
|
|
|
* @param string $secret
|
|
|
|
|
* @param string $uri
|
|
|
|
|
* @param string $method
|
|
|
|
|
* @param array $parameters
|
|
|
|
|
* @return string request signature
|
|
|
|
|
* @throws \App\Exceptions\Api\DamException If an error occurs.
|
|
|
|
|
*/
|
|
|
|
|
public static function signRequest(string $secret, string $uri, string $method, array $parameters): string
|
|
|
|
|
{
|
|
|
|
|
try {
|
|
|
|
|
$uri = collect(\parse_url($uri));
|
|
|
|
|
$method = \strtolower($method);
|
|
|
|
|
|
|
|
|
|
// * Remove signature from parameters to calculate the hashmac.
|
|
|
|
|
$signature = collect([
|
|
|
|
|
'uri' => sprintf(
|
|
|
|
|
'%s://%s%s',
|
|
|
|
|
$uri->get('scheme'),
|
|
|
|
|
$uri->get('host'),
|
|
|
|
|
$uri->get('path')
|
|
|
|
|
),
|
|
|
|
|
'method' => $method
|
|
|
|
|
]);
|
|
|
|
|
|
2022-07-28 12:32:37 +02:00
|
|
|
$parameters = collect(Arr::dot($parameters));
|
2022-07-26 10:38:32 +02:00
|
|
|
|
|
|
|
|
// * Remove signature from parameters.
|
|
|
|
|
$parameters->pull('signature');
|
|
|
|
|
|
|
|
|
|
// * Natural sort all parameters.
|
|
|
|
|
$parameters = $parameters->sortKeys(\SORT_NATURAL)
|
|
|
|
|
->map(function ($value, $key) {
|
|
|
|
|
return sprintf('%s=%s', \rawurlencode($key), \rawurlencode($value));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$signature->push($parameters->implode('&'));
|
|
|
|
|
|
|
|
|
|
$calculatedHash = base64_encode(hash_hmac(
|
|
|
|
|
'sha256',
|
|
|
|
|
$signature->implode('\n'),
|
|
|
|
|
Crypt::decryptString($secret),
|
|
|
|
|
true
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
if (!$calculatedHash) {
|
|
|
|
|
throw new DamException('Failed to calculate requests hash');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $calculatedHash;
|
|
|
|
|
} catch (DecryptException $e) {
|
|
|
|
|
throw new DamException('Failed to decrypt service credentials', 0, $e);
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
throw new DamException('An error occured when authenticating service', 0, $e);
|
|
|
|
|
} //end try
|
|
|
|
|
}
|
|
|
|
|
}
|