128 lines
3.0 KiB
JavaScript
128 lines
3.0 KiB
JavaScript
|
/**
|
||
|
* RateLimit class
|
||
|
* Based on classes/modules/core/RateLimit.class.php
|
||
|
*
|
||
|
* id: string to group similar calls
|
||
|
* allowed_calls: integer that represents the number of calls in the time_frame
|
||
|
* time_frame: integer number of seconds in which defined number of allowed_calls of specified id may be made
|
||
|
*
|
||
|
* Basic use case:
|
||
|
*
|
||
|
* RateLimit.setID( 101 ); //unique identifier for this group of calls
|
||
|
* RateLimit.setAllowedCalls( 10 ); //max number of calls in time frame
|
||
|
* RateLimit.setTimeFrame( 900 ); //15 minutes in seconds
|
||
|
* if ( RateLimit.check() ) {
|
||
|
* //do rate limited activity
|
||
|
* } else {
|
||
|
* //do not do rate limited activity
|
||
|
* }
|
||
|
*
|
||
|
*/
|
||
|
export var RateLimit = function() {
|
||
|
};
|
||
|
|
||
|
//attributes
|
||
|
RateLimit.memory = {};
|
||
|
RateLimit.id = '';
|
||
|
RateLimit.allowed_calls = 10;
|
||
|
RateLimit.time_frame = 3600; //1 hr
|
||
|
|
||
|
RateLimit.getID = function() {
|
||
|
return this.id;
|
||
|
};
|
||
|
RateLimit.setID = function( value ) {
|
||
|
if ( value != '' ) {
|
||
|
this.id = value;
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
};
|
||
|
|
||
|
RateLimit.getAllowedCalls = function() {
|
||
|
return this.allowed_calls;
|
||
|
};
|
||
|
RateLimit.setAllowedCalls = function( value ) {
|
||
|
if ( value != '' ) {
|
||
|
this.allowed_calls = value;
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
};
|
||
|
|
||
|
RateLimit.getTimeFrame = function() {
|
||
|
return this.time_frame;
|
||
|
};
|
||
|
RateLimit.setTimeFrame = function( value ) {
|
||
|
if ( value != '' ) {
|
||
|
this.time_frame = value;
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
};
|
||
|
|
||
|
RateLimit.getRateData = function() {
|
||
|
if ( typeof ( this.memory[this.id] ) == 'undefined' ) {
|
||
|
return null;
|
||
|
}
|
||
|
return this.memory[this.id];
|
||
|
};
|
||
|
RateLimit.setRateData = function( value ) {
|
||
|
if ( typeof ( this.memory[this.id] ) == 'undefined' ) {
|
||
|
this.memory[this.id] = {};
|
||
|
}
|
||
|
if ( value != '' ) {
|
||
|
this.memory[this.id] = value;
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
};
|
||
|
|
||
|
RateLimit.getAttempts = function() {
|
||
|
var rate_data = this.getRateData();
|
||
|
if ( Global.isSet( rate_data['attempts'] ) ) {
|
||
|
return rate_data['attempts'];
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @returns {boolean}
|
||
|
*/
|
||
|
RateLimit.check = function() {
|
||
|
if ( this.getID() != '' ) {
|
||
|
var rate_data = this.getRateData();
|
||
|
var new_time = ( new Date() ).getTime();
|
||
|
|
||
|
if ( Global.isSet( rate_data ) == false ) {
|
||
|
rate_data = {
|
||
|
first_date: new_time,
|
||
|
attempts: 0
|
||
|
};
|
||
|
} else if ( Global.isSet( rate_data ) ) {
|
||
|
|
||
|
var time_frame_milliseconds = this.getTimeFrame() * 1000;
|
||
|
if ( rate_data.attempts > this.getAllowedCalls() && rate_data.first_date >= ( new_time - time_frame_milliseconds ) ) {
|
||
|
Debug.Text( 'RateLimit limiting [' + rate_data.attempts + '/' + this.getAllowedCalls() + '] in ' + ( Math.floor( ( new_time - rate_data.first_date ) / 1000 ) ) + '/' + this.getTimeFrame() + 'sec', 'RateLimit.js', 'RateLimit', 'check', 10 );
|
||
|
return false;
|
||
|
} else if ( rate_data.first_date < new_time - time_frame_milliseconds ) {
|
||
|
rate_data = {
|
||
|
first_date: new_time,
|
||
|
attempts: 0
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
rate_data.attempts++;
|
||
|
this.setRateData( rate_data );
|
||
|
}
|
||
|
return true;
|
||
|
};
|
||
|
|
||
|
RateLimit.delete = function( id ) {
|
||
|
if ( id != null ) {
|
||
|
this.id = id;
|
||
|
}
|
||
|
delete this.memory[this.id];
|
||
|
};
|