mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-10-22 04:51:47 +00:00
Add rate limiting
This commit is contained in:
parent
ea08d28885
commit
471215fa7b
1 changed files with 46 additions and 12 deletions
|
|
@ -22,7 +22,7 @@ local API = {}
|
||||||
function API.new(app)
|
function API.new(app)
|
||||||
local Rojo = {}
|
local Rojo = {}
|
||||||
|
|
||||||
Rojo._notifRateLimit = {}
|
Rojo._rateLimit = {}
|
||||||
Rojo._permissions = Settings:get("apiPermissions") or {}
|
Rojo._permissions = Settings:get("apiPermissions") or {}
|
||||||
Rojo._changedEvent = Instance.new("BindableEvent")
|
Rojo._changedEvent = Instance.new("BindableEvent")
|
||||||
Rojo._apiDescriptions = {}
|
Rojo._apiDescriptions = {}
|
||||||
|
|
@ -121,10 +121,41 @@ function API.new(app)
|
||||||
return not not Rojo._permissions[source][key]
|
return not not Rojo._permissions[source][key]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local BUCKET, LIMIT = 10, 15
|
||||||
|
function Rojo:_checkRateLimit(api: string): boolean
|
||||||
|
local source = Rojo:_getCallerSource()
|
||||||
|
|
||||||
|
if Rojo._rateLimit[source] == nil then
|
||||||
|
Rojo._rateLimit[source] = {
|
||||||
|
[api] = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
elseif Rojo._rateLimit[source][api] == nil then
|
||||||
|
Rojo._rateLimit[source][api] = 0
|
||||||
|
|
||||||
|
elseif Rojo._rateLimit[source][api] >= LIMIT then
|
||||||
|
-- No more than LIMIT requests per BUCKET seconds
|
||||||
|
return true
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
Rojo._rateLimit[source][api] += 1
|
||||||
|
task.delay(BUCKET, function()
|
||||||
|
Rojo._rateLimit[source][api] -= 1
|
||||||
|
end)
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
function Rojo:RequestAccess(apis: {string}): {[string]: boolean}
|
function Rojo:RequestAccess(apis: {string}): {[string]: boolean}
|
||||||
assert(type(apis) == "table", "Rojo:RequestAccess expects an array of API names")
|
assert(type(apis) == "table", "Rojo:RequestAccess expects an array of API names")
|
||||||
assert(#apis > 0, "Rojo:RequestAccess expects an array of API names")
|
assert(#apis > 0, "Rojo:RequestAccess expects an array of API names")
|
||||||
|
|
||||||
|
if Rojo:_checkRateLimit("RequestAccess") then
|
||||||
|
-- Because this opens a popup, we dont want to let users get spammed by it
|
||||||
|
return {}
|
||||||
|
end
|
||||||
|
|
||||||
local source, name = Rojo:_getCallerSource(), Rojo:_getCallerName()
|
local source, name = Rojo:_getCallerSource(), Rojo:_getCallerName()
|
||||||
|
|
||||||
if Rojo._permissions[source] == nil then
|
if Rojo._permissions[source] == nil then
|
||||||
|
|
@ -185,11 +216,19 @@ function API.new(app)
|
||||||
assert(type(host) == "string" or host == nil, "Host must be type `string?`")
|
assert(type(host) == "string" or host == nil, "Host must be type `string?`")
|
||||||
assert(type(port) == "string" or port == nil, "Port must be type `string?`")
|
assert(type(port) == "string" or port == nil, "Port must be type `string?`")
|
||||||
|
|
||||||
|
if Rojo:_checkRateLimit("ConnectAsync") then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
app:startSession(host, port)
|
app:startSession(host, port)
|
||||||
end
|
end
|
||||||
|
|
||||||
Rojo._apiDescriptions.DisconnectAsync = "Disconnects from the Rojo server"
|
Rojo._apiDescriptions.DisconnectAsync = "Disconnects from the Rojo server"
|
||||||
function Rojo:DisconnectAsync()
|
function Rojo:DisconnectAsync()
|
||||||
|
if Rojo:_checkRateLimit("DisconnectAsync") then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
app:endSession()
|
app:endSession()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -204,6 +243,10 @@ function API.new(app)
|
||||||
function Rojo:SetSetting(setting: string, value: any)
|
function Rojo:SetSetting(setting: string, value: any)
|
||||||
assert(type(setting) == "string", "Setting must be type `string`")
|
assert(type(setting) == "string", "Setting must be type `string`")
|
||||||
|
|
||||||
|
if Rojo:_checkRateLimit("SetSetting") then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
return Settings:set(setting, value)
|
return Settings:set(setting, value)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -212,19 +255,10 @@ function API.new(app)
|
||||||
assert(type(msg) == "string", "Message must be type `string`")
|
assert(type(msg) == "string", "Message must be type `string`")
|
||||||
assert(type(timeout) == "number" or timeout == nil, "Timeout must be type `number?`")
|
assert(type(timeout) == "number" or timeout == nil, "Timeout must be type `number?`")
|
||||||
|
|
||||||
local source = Rojo:_getCallerSource()
|
if Rojo:_checkRateLimit("Notify") then
|
||||||
|
return
|
||||||
if Rojo._notifRateLimit[source] == nil then
|
|
||||||
Rojo._notifRateLimit[source] = 0
|
|
||||||
elseif Rojo._notifRateLimit[source] > 45 then
|
|
||||||
return -- Rate limited
|
|
||||||
end
|
end
|
||||||
|
|
||||||
Rojo._notifRateLimit[source] += 1
|
|
||||||
task.delay(30, function()
|
|
||||||
Rojo._notifRateLimit[source] -= 1
|
|
||||||
end)
|
|
||||||
|
|
||||||
app:addThirdPartyNotification(Rojo:_getCallerName(), msg, timeout)
|
app:addThirdPartyNotification(Rojo:_getCallerName(), msg, timeout)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue