You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

126 lines
3.6 KiB
Lua

local util = {}
local table_is_empty = function(t)
return next(t) == nil
end
local is_in = function(value, list)
for _,el in ipairs(list) do
if value == el then
return true
end
end
return false
end
util.hash = function(v) -- TODO: maybe use Argon2 [https://luarocks.org/modules/thibaultcha/argon2]
--xxhash:update(v)
--return xxhash:digest()
return v
end
--[[
Uses 'schema' to verify:
Existence of required value in 'req'
They have proper types
The DB references actually exist
]]
--[[ schema = {
user_id = {'db_ref', to='user', required=true, load_as='user_record'} -- `load_as` so a DB search doesn't have to be done again after validation
price = {'number', required=true}
}
]]
util.validate = function(req, schema, db, sessions)
local errors = {}
local loaded_records = {}
for property, rules in pairs(schema) do
local expected_value_type = rules[1]
local value = req[property]
if rules.required == true then
if value == nil then
table.insert(errors, "Expected '"..property.."' to be provided.")
end
end
if expected_value_type == 'number' or expected_value_type == 'string' or expected_value_type == 'table' then
if type(value) ~= expected_value_type then
table.insert(errors, "Expected '"..property.."' to be a "..expected_value_type..".")
elseif rules.is_any_of ~= nil then
if not is_in(value, rules.is_any_of) then
table.insert(errors, "Expected '"..property.."' to be one of (".. table.concat(rules.is_any_of,',') ..").")
end
end
elseif expected_value_type == 'db_ref' then
local expected_record_type = rules.to
local record = db:findOne(function(record) return record.id == value and record.type == expected_record_type end)
if record == nil then
table.insert(errors, "Expected '"..property.."' to point to a '"..expected_record_type.."' in the database.")
else
loaded_records[rules.load_as] = record
end
elseif expected_value_type == 'base64' then
local _, start_of_base64_string_index = string.find(value, "data:.-/.-;base64,")
start_of_base64_string_index = start_of_base64_string_index + 1
local base64_adjusted = string.sub(value, start_of_base64_string_index) -- must remove "data:*/*;base64," from the beginning of the string
loaded_records[rules.load_as] = base64_adjusted
elseif expected_value_type == 'session' then
local session = sessions[value]
if session == nil then
table.insert(errors, "No such session.")
else
if rules.is_admin == true and db:getrecord(session.user_id).is_admin ~= true then
table.insert(errors, "Current user is not admin.")
else
loaded_records.session = session
end
end
end
end
return errors, loaded_records
end
util.run_every = function(interval_in_s, fn)
local co = coroutine.create(function()
local t1 = os.time()
while true do
if os.time()-t1 > interval_in_s*1000 then
fn()
t1 = os.time()
end
coroutine.yield()
--posix.unistd.sleep(interval_in_s)
end
end)
return co
end
util.setdefaults = function(t, defaults)
for k,v in pairs(defaults) do
if t[k] == nil then
t[k] = v
end
end
end
util.merge = function(dest, source)
for k,v in pairs(source) do
dest[k] = v
end
end
util.findOne = function(t, fn)
for i,v in ipairs(t) do
if fn(v, i) then return v end
end
return nil
end
util.removefromtable = function(t, v)
local i = 1
while t[i] ~= v do i = i + 1 end
table.remove(t, i)
return i
end
return util