1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-20 08:21:34 +02:00
invoiceninja/app/Http/Middleware/ApiCheck.php

91 lines
3.0 KiB
PHP
Raw Normal View History

2015-04-02 15:06:16 +02:00
<?php namespace App\Http\Middleware;
use Closure;
use Utils;
use Request;
use Session;
use Response;
2015-04-08 20:19:58 +02:00
use Auth;
use Cache;
2015-04-02 15:06:16 +02:00
use App\Models\AccountToken;
class ApiCheck {
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
2016-03-08 22:22:59 +01:00
$loggingIn = $request->is('api/v1/login') || $request->is('api/v1/register');
2015-04-02 15:06:16 +02:00
$headers = Utils::getApiHeaders();
2016-06-05 17:50:41 +02:00
if ($secret = env(API_SECRET)) {
$hasApiSecret = hash_equals($request->api_secret ?: '', $secret);
}
2015-04-02 15:06:16 +02:00
2015-11-02 19:43:22 +01:00
if ($loggingIn) {
2016-03-08 22:22:59 +01:00
// check API secret
2016-05-29 16:31:03 +02:00
if ( ! $hasApiSecret) {
2016-03-08 22:22:59 +01:00
sleep(ERROR_DELAY);
return Response::json('Invalid secret', 403, $headers);
}
2015-04-02 15:06:16 +02:00
} else {
2015-11-02 19:43:22 +01:00
// check for a valid token
$token = AccountToken::where('token', '=', Request::header('X-Ninja-Token'))->first(['id', 'user_id']);
2016-05-08 20:50:35 +02:00
// check if user is archived
if ($token && $token->user) {
2015-11-02 19:43:22 +01:00
Auth::loginUsingId($token->user_id);
Session::set('token_id', $token->id);
} else {
2016-03-08 22:22:59 +01:00
sleep(ERROR_DELAY);
2015-11-08 21:34:26 +01:00
return Response::json('Invalid token', 403, $headers);
2015-11-02 19:43:22 +01:00
}
2015-04-02 15:06:16 +02:00
}
2015-11-02 19:43:22 +01:00
if (!Utils::isNinja() && !$loggingIn) {
2015-05-13 17:32:59 +02:00
return $next($request);
2015-04-02 15:06:16 +02:00
}
2016-05-29 16:31:03 +02:00
if (!Utils::hasFeature(FEATURE_API) && !$hasApiSecret) {
2015-11-08 21:34:26 +01:00
return Response::json('API requires pro plan', 403, $headers);
2015-04-02 15:06:16 +02:00
} else {
2015-11-02 19:43:22 +01:00
$key = Auth::check() ? Auth::user()->account->id : $request->getClientIp();
2015-04-02 15:06:16 +02:00
// http://stackoverflow.com/questions/1375501/how-do-i-throttle-my-sites-api-users
$hour = 60 * 60;
$hour_limit = 100; # users are limited to 100 requests/hour
2015-11-02 19:43:22 +01:00
$hour_throttle = Cache::get("hour_throttle:{$key}", null);
$last_api_request = Cache::get("last_api_request:{$key}", 0);
2015-04-02 15:06:16 +02:00
$last_api_diff = time() - $last_api_request;
2016-05-29 16:31:03 +02:00
2015-04-02 15:06:16 +02:00
if (is_null($hour_throttle)) {
$new_hour_throttle = 0;
} else {
$new_hour_throttle = $hour_throttle - $last_api_diff;
$new_hour_throttle = $new_hour_throttle < 0 ? 0 : $new_hour_throttle;
$new_hour_throttle += $hour / $hour_limit;
$hour_hits_remaining = floor(( $hour - $new_hour_throttle ) * $hour_limit / $hour);
$hour_hits_remaining = $hour_hits_remaining >= 0 ? $hour_hits_remaining : 0;
}
if ($new_hour_throttle > $hour) {
$wait = ceil($new_hour_throttle - $hour);
sleep(1);
2015-11-08 21:34:26 +01:00
return Response::json("Please wait {$wait} second(s)", 403, $headers);
2015-04-02 15:06:16 +02:00
}
2015-11-02 19:43:22 +01:00
Cache::put("hour_throttle:{$key}", $new_hour_throttle, 10);
Cache::put("last_api_request:{$key}", time(), 10);
2015-04-02 15:06:16 +02:00
}
return $next($request);
}
2016-05-29 16:31:03 +02:00
}