mirror of
https://github.com/pierre42100/ComunicAPI
synced 2024-11-30 09:16:35 +00:00
Setup API requests limit system.
This commit is contained in:
parent
fba6c796a8
commit
4c74b9c414
@ -17,10 +17,14 @@ class accountController {
|
|||||||
* @url POST /account/login
|
* @url POST /account/login
|
||||||
*/
|
*/
|
||||||
public function connectUSER(){
|
public function connectUSER(){
|
||||||
|
|
||||||
//Check variables sent in request
|
//Check variables sent in request
|
||||||
if(!isset($_POST['userMail']) OR !isset($_POST['userPassword']))
|
if(!isset($_POST['userMail']) OR !isset($_POST['userPassword']))
|
||||||
throw new RestException(400, "Missing data !");
|
throw new RestException(400, "Missing data !");
|
||||||
|
|
||||||
|
//API limit
|
||||||
|
api_limit_query(APILimits::ACTION_LOGIN_FAILED, false);
|
||||||
|
|
||||||
//Retrieve database connection
|
//Retrieve database connection
|
||||||
$db = CS::get()->db;;
|
$db = CS::get()->db;;
|
||||||
|
|
||||||
@ -31,8 +35,11 @@ class accountController {
|
|||||||
//Try to perform login
|
//Try to perform login
|
||||||
$loginTokens = CS::get()->components->account->generateUserLoginTokens($userMail, $userPassword, APIServiceID, $db);
|
$loginTokens = CS::get()->components->account->generateUserLoginTokens($userMail, $userPassword, APIServiceID, $db);
|
||||||
|
|
||||||
if(count($loginTokens) == 0)
|
if(count($loginTokens) == 0){
|
||||||
|
api_limit_query(APILimits::ACTION_LOGIN_FAILED, true);
|
||||||
throw new RestException(401, "Invalid e-mail address / password !");
|
throw new RestException(401, "Invalid e-mail address / password !");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//Return result with tokens
|
//Return result with tokens
|
||||||
return array(
|
return array(
|
||||||
|
135
classes/APILimits.php
Normal file
135
classes/APILimits.php
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* API Actions limits count
|
||||||
|
*
|
||||||
|
* @author Pierre HUBERT
|
||||||
|
*/
|
||||||
|
|
||||||
|
class APILimits {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table name
|
||||||
|
*/
|
||||||
|
const TABLE_NAME = DBprefix."api_limit_count";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entries live time
|
||||||
|
*/
|
||||||
|
const KEEP_DATA_FOR = 3600; // 1 hour
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actions list
|
||||||
|
*/
|
||||||
|
const ACTION_LOGIN_FAILED = "failed_login";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actions configruation
|
||||||
|
*/
|
||||||
|
const ACTIONS = array(
|
||||||
|
|
||||||
|
//Login failed
|
||||||
|
self::ACTION_LOGIN_FAILED => array(
|
||||||
|
"limit" => 10
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Limit the number of time a client can perform a query over the API
|
||||||
|
*
|
||||||
|
* @param string $action The name of the action to limit
|
||||||
|
* @param bool $trigger Specify whether this call of the method must be
|
||||||
|
* considered as a call of the client or not
|
||||||
|
*/
|
||||||
|
public function limit_query(string $action, bool $trigger){
|
||||||
|
|
||||||
|
//First, clean old entries
|
||||||
|
$this->clean();
|
||||||
|
|
||||||
|
$ip = $_SERVER["REMOTE_ADDR"];
|
||||||
|
|
||||||
|
//If required, increase action by one
|
||||||
|
if($trigger)
|
||||||
|
$this->trigger($action, $ip);
|
||||||
|
|
||||||
|
//Count the number of time the action occurred
|
||||||
|
if($this->count($action, $ip) > self::ACTIONS[$action]["limit"])
|
||||||
|
Rest_fatal_error(429, "Too many request. Please try again later.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean old entries
|
||||||
|
*/
|
||||||
|
public function clean(){
|
||||||
|
db()->deleteEntry(
|
||||||
|
self::TABLE_NAME,
|
||||||
|
"time_start < ?",
|
||||||
|
array(time() - self::KEEP_DATA_FOR)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increase by one the number of the time a client performed
|
||||||
|
* an action
|
||||||
|
*
|
||||||
|
* @param string $action The action to trigger
|
||||||
|
* @param string $ip The target IP address
|
||||||
|
* @return bool TRUE for a success else FALSE
|
||||||
|
*/
|
||||||
|
private function trigger(string $action, string $ip) : bool {
|
||||||
|
|
||||||
|
if(!$this->exists($action, $ip)){
|
||||||
|
return db()->addLine(self::TABLE_NAME, array(
|
||||||
|
"ip" => $ip,
|
||||||
|
"time_start" => time(),
|
||||||
|
"action" => $action,
|
||||||
|
"count" => 1
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
|
||||||
|
$number = $this->count($action, $ip);
|
||||||
|
$number++;
|
||||||
|
|
||||||
|
return db()->updateDB(self::TABLE_NAME,
|
||||||
|
"ip = ? AND action = ?",
|
||||||
|
array("count" => $number),
|
||||||
|
array($ip, $action));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check wether an action has been referenced at least once in
|
||||||
|
* the database
|
||||||
|
*
|
||||||
|
* @param string $action The action to check
|
||||||
|
* @param string $ip The target IP address
|
||||||
|
* @return bool TRUE if the entry has been found at least once / FALSE else
|
||||||
|
*/
|
||||||
|
private function exists(string $action, string $ip) : bool {
|
||||||
|
return db()->count(self::TABLE_NAME,
|
||||||
|
"WHERE ip = ? AND action = ?",
|
||||||
|
array($ip, $action)) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count the number of time an IP address has performed an action
|
||||||
|
*
|
||||||
|
* @param string $action The target action
|
||||||
|
* @param string $ip Target IP address
|
||||||
|
* @return int The number of time the action has been done
|
||||||
|
*/
|
||||||
|
private function count(string $action, string $ip) : int {
|
||||||
|
$data = db()->select(self::TABLE_NAME,
|
||||||
|
"WHERE ip = ? AND action = ?",
|
||||||
|
array($ip, $action),
|
||||||
|
array("count"));
|
||||||
|
|
||||||
|
if(count($data) < 1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
else
|
||||||
|
return $data[0]["count"];
|
||||||
|
}
|
||||||
|
}
|
@ -72,6 +72,14 @@ CREATE TABLE `commentaires` (
|
|||||||
PRIMARY KEY (`ID`)
|
PRIMARY KEY (`ID`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `comunic_api_limit_count`;
|
||||||
|
CREATE TABLE `comunic_api_limit_count` (
|
||||||
|
`ip` varchar(15) NOT NULL,
|
||||||
|
`time_start` int(11) DEFAULT NULL,
|
||||||
|
`action` varchar(45) DEFAULT NULL,
|
||||||
|
`count` int(11) DEFAULT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `comunic_API_ServicesToken`;
|
DROP TABLE IF EXISTS `comunic_API_ServicesToken`;
|
||||||
CREATE TABLE `comunic_API_ServicesToken` (
|
CREATE TABLE `comunic_API_ServicesToken` (
|
||||||
|
16
helpers/APILimits.php
Normal file
16
helpers/APILimits.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* API Limits helper
|
||||||
|
*
|
||||||
|
* @author Pierre HUBERT
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Limit the number of time a query can be performed by a client
|
||||||
|
*
|
||||||
|
* @param string $name The name of the action to limit
|
||||||
|
* @param bool $trigger Count this as an action of the user or not
|
||||||
|
*/
|
||||||
|
function api_limit_query(string $name, bool $trigger){
|
||||||
|
cs()->limit->limit_query($name, $trigger);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user