Compare commits

...

5 Commits

Author SHA1 Message Date
Luna c15abe3c05 fix main script usage of ctx 2022-12-06 15:54:16 -03:00
Luna 5d21c975ea add test suite 2022-12-06 15:53:20 -03:00
Luna 06924d10f6 let filters customize status code and body 2022-12-06 14:52:20 -03:00
Luna a747fe8182 add initialization callback for filters 2022-12-06 14:52:09 -03:00
Luna eefdecb1e9 use request uri and regex to choose callbacks 2022-12-06 13:48:09 -03:00
6 changed files with 180 additions and 45 deletions

View File

@ -11,3 +11,11 @@ on top of ActivityPub implementations.
- write test suite
- create install instructions
## Testing
```
luarocks-5.1 install --local luaunit
luarocks-5.1 install --local lrexlib-PCRE2
eval (luarocks-5.1 path --bin)
lua5.1 test.lua
```

48
ctx.lua Normal file
View File

@ -0,0 +1,48 @@
function log(msg)
ngx.log(ngx.STDERR, tostring(msg))
end
local ctx = {}
function ctx:setWantedScripts(graph)
self._wanted_scripts = graph
end
function ctx:loadChain()
self.compiled_chain = {}
for module_name, module_config in pairs(self._wanted_scripts) do
local module = require(module_name)
local module_state = module.init(module_config)
-- TODO is it possible to make module_config readonly?
table.insert(self.compiled_chain, {module, module_config, module_state})
end
end
function ctx:onRequest()
local request_uri = ngx.var.uri
-- find out which modules to call based on their regexes
local callbacks_to_call = {}
for _, filter in ipairs(self.compiled_chain) do
local module, module_config, state = unpack(filter)
for callback_regex, callback_function in pairs(module.callbacks) do
local match, error = ngx.re.match(request_uri, callback_regex)
if match then
table.insert(callbacks_to_call, {callback_function, module_config, state})
end
end
end
for _,tuple in ipairs(callbacks_to_call) do
local callback_function, config, state = unpack(tuple)
local status_code, body = callback_function(config, state)
if status_code ~= nil then
ngx.status = status_code
ngx.say(body or "request denied")
ngx.exit(status_code)
end
end
end
return ctx

View File

@ -7,38 +7,13 @@ local CONFIG_PATH = ".;/etc/aproxy"
--
-- local config = loadConfig()
function log(msg)
ngx.log(ngx.STDERR, tostring(msg))
local ctx = require('ctx')
ctx:setWantedScripts({
['scripts.webfinger_allowlist'] = {accounts = {"example@example.com"}}
})
ctx:loadChain()
return function()
ctx:onRequest()
end
local WANTED_SCRIPTS = {
'scripts.webfinger_allowlist'
}
local compiled_chain = {}
for _, module_name in pairs(WANTED_SCRIPTS) do
log('load module', module_name)
mod = require(module_name)
log('load module', mod)
table.insert(compiled_chain, mod)
end
local function onRequest()
log('AWOOOOGA')
for _,mod in ipairs(compiled_chain) do
log(mod)
local mod_config = {accounts = {"a@a.com"}}
local result, body = mod.callback(mod_config)
log(result)
log(body)
if not result then
ngx.status = 400
ngx.say(body or "request denied")
ngx.exit(400)
end
end
end
return onRequest

View File

@ -1,19 +1,23 @@
function webfingerCallback(cfg)
function webfingerInit(cfg)
local accounts_set = {}
for _, account in ipairs(cfg.accounts) do
accounts_set["acct:" .. account] = true
end
return accounts_set
end
function webfingerCallback(cfg, accounts_set)
local args, err = ngx.req.get_uri_args()
if err == "truncated" then
return false, 'uri args too long'
return 400, 'uri args too long'
end
local resource = args['resource']
if resource ~= nil then
for _, account in ipairs(cfg.accounts) do
if resource == account then
return true
end
end
if accounts_set[resource] then
return nil
else
return 404, "Couldn't find user"
end
return false
end
return {
@ -27,7 +31,7 @@ return {
Useful for small instances.
]],
apiVersion=1,
callback=webfingerCallback,
init=webfingerInit,
callbacks = {
['/.well-known/webfinger'] = webfingerCallback
},

77
test.lua Normal file
View File

@ -0,0 +1,77 @@
lu = require('luaunit')
local rex = require('rex_pcre2')
function createNgx()
local ngx = {
status = nil
}
local function mockedThing(self, property)
return function(value)
self['_'..property] = value
end
end
ngx.say = mockedThing(ngx, "say")
ngx.exit = mockedThing(ngx, "exit")
ngx.log = function (_, msg)
print(msg)
end
-- only hold data here
ngx.var = {}
-- request params api
ngx.req = {}
ngx.req.get_uri_args = function ()
return ngx._uri_args
end
ngx.req.set_uri_args = function (val)
ngx._uri_args = val
end
-- regex api
ngx.re = {}
ngx.re.match = rex.match
ngx.re.search = rex.find
return ngx
end
function resetNgx()
ngx = createNgx()
end
teardownNgx = resetNgx
function setupFakeRequest(path, options)
ngx.var.uri = path
if options.params then
ngx.req.set_uri_args(options.params)
end
end
local ctx = require('ctx')
function setupTest(module_require_path, config)
resetNgx()
local module = require(module_require_path)
state = module.init(config)
ctx.compiled_chain = {
{module, config, state}
}
return module
end
function onRequest()
ctx:setWantedScripts()
local ctx = require('ctx')
do
ctx:onRequest()
end
end
require('tests.webfinger_allowlist')
os.exit(lu.LuaUnit.run())

View File

@ -0,0 +1,23 @@
TestWebfinger = {}
function TestWebfinger:setup()
self.mod = setupTest('scripts.webfinger_allowlist', {accounts = {'correct@example.org'}})
end
local WEBFINGER_PATH = '/.well-known/webfinger'
function TestWebfinger:testCorrectAccount()
setupFakeRequest(WEBFINGER_PATH, { params = {resource = 'acct:correct@example.org'} })
onRequest()
lu.assertIs(ngx.status, nil)
end
function TestWebfinger:testWrongAccount()
setupFakeRequest(WEBFINGER_PATH, { params = {resource = 'acct:wrong@example.org'} })
onRequest()
lu.assertIs(ngx.status, 404)
end
function TestWebfinger:teardown()
teardownNgx()
end