refactor: use OOP where appropriate
parent
d390f32dea
commit
7e2e2bcf49
2
Makefile
2
Makefile
|
@ -29,7 +29,7 @@ test: test-env
|
|||
${run_test_file} ${ROOT_DIR}/test/config.utest.lua
|
||||
${run_test_file} ${ROOT_DIR}/test/auth.utest.lua
|
||||
${run_test_file} ${ROOT_DIR}/test/nginx.utest.lua
|
||||
${run_test_file} ${ROOT_DIR}/test/profile.utest.lua
|
||||
${run_test_file} ${ROOT_DIR}/test/identity.utest.lua
|
||||
${run_test_file} ${ROOT_DIR}/test/sites.utest.lua
|
||||
${run_test_file} ${ROOT_DIR}/test/crypto.utest.lua
|
||||
${run_test_file} ${ROOT_DIR}/test/login.utest.lua
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
|
||||
local nginx = require("ssso_nginx")
|
||||
|
||||
local req_data = nginx.get_request()
|
||||
local req_data = nginx.class__request:current()
|
||||
|
||||
if nginx.is(req_data, "/.well-known/webfinger")
|
||||
and nginx.has_param(req_data, "rel", "http://openid.net/specs/connect/1.0/issuer")
|
||||
and nginx.has_param(req_data, "resource")
|
||||
if req_data:is("/.well-known/webfinger")
|
||||
and req_data:has_param("rel", "http://openid.net/specs/connect/1.0/issuer")
|
||||
and req_data:has_param("resource")
|
||||
then
|
||||
-- https://openid.net/specs/openid-connect-discovery-1_0.html
|
||||
local oauth2 = require("ssso_oauth2")
|
||||
|
@ -27,14 +27,14 @@ local sites = require("ssso_sites")
|
|||
local sso_prefix = conf.get_sso_prefix()
|
||||
local auth, status = sess.get_session()
|
||||
|
||||
if nginx.starts_with(req_data, sso_prefix) then
|
||||
if req_data:starts_with(sso_prefix) then
|
||||
|
||||
-- SSO-specific URL
|
||||
|
||||
if nginx.starts_with(req_data, sso_prefix .. "/login") then
|
||||
if req_data:starts_with(sso_prefix .. "/login") then
|
||||
local login = require("ssso_login")
|
||||
return login.answer_request(req_data)
|
||||
elseif nginx.starts_with(req_data, sso_prefix .. "/oauth2") then
|
||||
elseif req_data:starts_with(sso_prefix .. "/oauth2") then
|
||||
local oauth2 = require("ssso_oauth2")
|
||||
return oauth2.answer_request(req_data, auth)
|
||||
elseif auth then
|
||||
|
|
|
@ -7,7 +7,7 @@ local function load_conf(prefix)
|
|||
local file = assert(io.open(prefix .. name_suffix, "r"), "File " .. prefix .. name_suffix .. " not found")
|
||||
conf = json.decode(file:read("*all"))
|
||||
file:close()
|
||||
assert(conf["auth"], "Simple-SSO configuration is missing a `auth` entry")
|
||||
assert(conf["auth"], "Simple-SSO configuration is missing an `auth` entry")
|
||||
assert(conf["sso_host"], "Simple-SSO configuration is missing a `sso_host` entry")
|
||||
assert(conf["sso_prefix"], "Simple-SSO configuration is missing a `sso_prefix` entry")
|
||||
assert(conf["session_seconds"], "Simple-SSO configuration is missing a `session_seconds` entry")
|
||||
|
|
|
@ -7,7 +7,6 @@ local b64 = require("ssso_base64")
|
|||
local config = require("ssso_config")
|
||||
local log = require("ssso_log")
|
||||
local nginx = require("ssso_nginx")
|
||||
local prof = require("ssso_profile")
|
||||
local sites = require("ssso_sites")
|
||||
|
||||
local KEY_SIZE = 32 -- 256 bits for AES-256-GCM’s key and SHA-256
|
||||
|
@ -88,12 +87,12 @@ end
|
|||
|
||||
-- https://www.rfc-editor.org/rfc/rfc7519
|
||||
-- https://openid.net/specs/openid-connect-core-1_0.html
|
||||
local function get_jws_and_tslimit(data)
|
||||
local user = prof.user(data)
|
||||
local ser_data = prof.serialize(data) .. sites.serialize(data)
|
||||
log.debug("Creating JWS with data: " .. ser_data:gsub("([\031\030\029\028])", function(s) return "[" .. s:byte() .. "]" end))
|
||||
local crypted_data = encrypt(ser_data)
|
||||
if not user or not crypted_data then
|
||||
local function get_jws_and_tslimit(profile)
|
||||
local user = profile:user()
|
||||
local ser_profile = profile:serialize()
|
||||
log.debug("Creating JWS with profile: " .. ser_profile:gsub("([\031\030\029\028\027\026])", function(s) return "[" .. s:byte() .. "]" end))
|
||||
local crypted_profile = encrypt(ser_profile)
|
||||
if not user or not crypted_profile then
|
||||
return nil, nil
|
||||
end
|
||||
local iat = nginx.get_seconds_since_epoch()
|
||||
|
@ -104,30 +103,29 @@ local function get_jws_and_tslimit(data)
|
|||
aud = user,
|
||||
exp = exp,
|
||||
iat = iat,
|
||||
x_ssso = b64.encode_base64url(crypted_data),
|
||||
x_ssso = b64.encode_base64url(crypted_profile),
|
||||
}
|
||||
return to_jws(jwt), exp
|
||||
end
|
||||
|
||||
local function get_data_and_new_jws(jws)
|
||||
local function get_profile_and_new_jws(jws)
|
||||
local jwt = to_jwt(jws)
|
||||
local iat = nginx.get_seconds_since_epoch()
|
||||
if jwt == nil or not jwt["x_ssso"] or not jwt["exp"] or jwt.exp < iat then
|
||||
return nil, nil, nil
|
||||
end
|
||||
local ser_data = decrypt(b64.decode_base64url(jwt.x_ssso))
|
||||
if not ser_data then
|
||||
local ser_profile = decrypt(b64.decode_base64url(jwt.x_ssso))
|
||||
if not ser_profile then
|
||||
return nil, nil, nil
|
||||
end
|
||||
log.debug("Read data from JWS: " .. ser_data:gsub("([\031\030\029\028])", function(s) return "[" .. s:byte() .. "]" end))
|
||||
local data, remainder, _ = prof.deserialize(ser_data)
|
||||
data, _ = sites.deserialize_update(remainder, data)
|
||||
log.debug("Read profile from JWS: " .. ser_profile:gsub("([\031\030\029\028])", function(s) return "[" .. s:byte() .. "]" end))
|
||||
local profile = sites.class__profile:deserialize(ser_profile)
|
||||
jwt.iat = iat
|
||||
jwt.exp = iat + config.get_session_seconds()
|
||||
return data, to_jws(jwt), jwt.exp
|
||||
return profile, to_jws(jwt), jwt.exp
|
||||
end
|
||||
|
||||
return {
|
||||
get_jws_and_tslimit = get_jws_and_tslimit,
|
||||
get_data_and_new_jws = get_data_and_new_jws,
|
||||
get_profile_and_new_jws = get_profile_and_new_jws,
|
||||
}
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
local b64 = require("ssso_base64")
|
||||
|
||||
local class__identity = {}
|
||||
|
||||
function class__identity:build(user, password, name, email)
|
||||
local identity = {
|
||||
u = user,
|
||||
p = password,
|
||||
n = name,
|
||||
e = email,
|
||||
}
|
||||
setmetatable(identity, {__index = self})
|
||||
return identity
|
||||
end
|
||||
|
||||
function class__identity:serialize() -- TODO: test
|
||||
return (self.u or "\025")
|
||||
.. "\031" .. (self.p or "\025")
|
||||
.. "\031" .. (self.n or "\025")
|
||||
.. "\031" .. (self.e or "\025")
|
||||
end
|
||||
|
||||
function class__identity:deserialize(ser) -- TODO: test
|
||||
local identity
|
||||
ser:gsub("^(.-)\031(.-)\031(.-)\031(.*)", function (u, p, n, e)
|
||||
if u == "\025" then u = nil end
|
||||
if p == "\025" then p = nil end
|
||||
if n == "\025" then n = nil end
|
||||
if e == "\025" then e = nil end
|
||||
identity = self:build(u, p, n, e)
|
||||
end)
|
||||
return identity
|
||||
end
|
||||
|
||||
function class__identity:format(template)
|
||||
local s = template
|
||||
s = s:gsub("\ru%.", self.u or "")
|
||||
s = s:gsub("\rp%.", self.p or "")
|
||||
s = s:gsub("\rn%.", self.n or "")
|
||||
s = s:gsub("\re%.", self.e or "")
|
||||
s = s:gsub("\rb64%(([^\r]-)%)%.", function(x) return b64.encode_base64(x) end)
|
||||
s = s:gsub("\ru64%(([^\r]-)%)%.", function(x) return b64.encode_base64url(x) end)
|
||||
return s
|
||||
end
|
||||
|
||||
function class__identity:email()
|
||||
return self.e
|
||||
end
|
||||
|
||||
function class__identity:name()
|
||||
return self.n
|
||||
end
|
||||
|
||||
function class__identity:user()
|
||||
return self.u
|
||||
end
|
||||
|
||||
return {
|
||||
class__identity = class__identity,
|
||||
}
|
|
@ -3,7 +3,6 @@ local conf = require("ssso_config")
|
|||
local crypto = require("ssso_crypto")
|
||||
local log = require("ssso_log")
|
||||
local nginx = require("ssso_nginx")
|
||||
local prof = require("ssso_profile")
|
||||
local sites = require("ssso_sites")
|
||||
local util = require("ssso_util")
|
||||
|
||||
|
@ -51,15 +50,14 @@ local function check_credentials_and_get_profile(user, password)
|
|||
local user_data = auth.read_user(user, password)
|
||||
if user_data then
|
||||
log.debug("Credentials accepted for user " .. user_data.name)
|
||||
local profile = prof.build_profile(user, password, user_data.name, user_data.email)
|
||||
return sites.with_sites(profile, user)
|
||||
return sites.class__profile:build_from_conf(user, password, user_data.name, user_data.email)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
local function check_login(req_data)
|
||||
req_data = nginx.with_post_parameters(req_data)
|
||||
req_data = req_data:with_post_parameters()
|
||||
local user = req_data.query_params["login"] or ""
|
||||
local password = req_data.query_params["password"] or ""
|
||||
local profile = check_credentials_and_get_profile(user, password)
|
||||
|
@ -88,17 +86,17 @@ end
|
|||
|
||||
local function answer_request(req_data)
|
||||
local login = conf.get_sso_prefix() .. "/login"
|
||||
if nginx.is(req_data, login) then
|
||||
if nginx.has_method(req_data, "POST") then
|
||||
if req_data:is(login) then
|
||||
if req_data:has_method("POST") then
|
||||
log.info("Checking login")
|
||||
return check_login(req_data)
|
||||
else
|
||||
local html = inject_data(contents("login.html"), req_data, nil)
|
||||
return nginx.return_contents(html, "text/html; charset=UTF-8")
|
||||
end
|
||||
elseif nginx.is(req_data, login .. ".css") then
|
||||
elseif req_data:is(login .. ".css") then
|
||||
return nginx.return_contents(contents("login.css"), "text/css; charset=UTF-8")
|
||||
elseif nginx.is(req_data, login .. ".js") then
|
||||
elseif req_data:is(login .. ".js") then
|
||||
return nginx.return_contents(contents("login.js"), "application/javascript; charset=UTF-8")
|
||||
else
|
||||
log.info("Unknown login file")
|
||||
|
|
|
@ -3,7 +3,14 @@ local b64 = require("ssso_base64")
|
|||
local util = require("ssso_util")
|
||||
local conf = require("ssso_config")
|
||||
|
||||
local function get_request()
|
||||
local class__request = {}
|
||||
|
||||
local function str_starts_with(str, begin)
|
||||
local i, _ = str:find(util.str_to_pattern(begin))
|
||||
return 1 == i
|
||||
end
|
||||
|
||||
function class__request:current()
|
||||
local vars = ngx.var
|
||||
local request = {
|
||||
referer = vars.http_referer,
|
||||
|
@ -11,6 +18,8 @@ local function get_request()
|
|||
method = vars.request_method,
|
||||
uri = vars.request_uri,
|
||||
}
|
||||
setmetatable(request, {__index = self})
|
||||
|
||||
if request.referer == "" then
|
||||
request.referer = nil
|
||||
end
|
||||
|
@ -33,20 +42,35 @@ local function get_request()
|
|||
return request
|
||||
end
|
||||
|
||||
local function with_post_parameters(req_data)
|
||||
function class__request:with_post_parameters()
|
||||
ngx.req.read_body()
|
||||
local args, _ = ngx.req.get_post_args()
|
||||
if args then
|
||||
for key, val in pairs(args) do
|
||||
req_data.query_params[key] = val
|
||||
self.query_params[key] = val
|
||||
end
|
||||
end
|
||||
return req_data
|
||||
return self
|
||||
end
|
||||
|
||||
local function str_starts_with(str, begin)
|
||||
local i, _ = str:find(util.str_to_pattern(begin))
|
||||
return 1 == i
|
||||
function class__request:has_method(method)
|
||||
return string.upper(method) == string.upper(self.method)
|
||||
end
|
||||
|
||||
function class__request:is(url)
|
||||
return self.target == url
|
||||
end
|
||||
|
||||
function class__request:matches(lua_pattern)
|
||||
return self.target:match(lua_pattern)
|
||||
end
|
||||
|
||||
function class__request:starts_with(prefix)
|
||||
return str_starts_with(self.target, prefix)
|
||||
end
|
||||
|
||||
function class__request:has_param(param, value)
|
||||
return self.query_params[param] ~= nil and (value == nil or self.query_params[param] == value)
|
||||
end
|
||||
|
||||
local function get_basic_auth()
|
||||
|
@ -103,26 +127,6 @@ local function add_header(name, value)
|
|||
ngx.req.set_header(name, value)
|
||||
end
|
||||
|
||||
local function has_method(req_data, method)
|
||||
return string.upper(method) == string.upper(req_data.method)
|
||||
end
|
||||
|
||||
local function is(req_data, url)
|
||||
return req_data.target == url
|
||||
end
|
||||
|
||||
local function matches(req_data, lua_pattern)
|
||||
return req_data.target:match(lua_pattern)
|
||||
end
|
||||
|
||||
local function starts_with(req_data, prefix)
|
||||
return str_starts_with(req_data.target, prefix)
|
||||
end
|
||||
|
||||
local function has_param(req_data, param, value)
|
||||
return req_data.query_params[param] ~= nil and (value == nil or req_data.query_params[param] == value)
|
||||
end
|
||||
|
||||
local function answer_not_found(req_data)
|
||||
return ngx.exit(404)
|
||||
end
|
||||
|
@ -167,21 +171,15 @@ return {
|
|||
add_cookie = add_cookie,
|
||||
add_header = add_header,
|
||||
answer_not_found = answer_not_found,
|
||||
class__request = class__request,
|
||||
forward_request = forward_request,
|
||||
get_basic_auth = get_basic_auth,
|
||||
get_jws_cookie = get_jws_cookie,
|
||||
get_request = get_request,
|
||||
get_seconds_since_epoch = get_seconds_since_epoch,
|
||||
has_method = has_method,
|
||||
has_param = has_param,
|
||||
is = is,
|
||||
matches = matches,
|
||||
redirect_to_login = redirect_to_login,
|
||||
redirect_to_page = redirect_to_page,
|
||||
redirect_to_portal = redirect_to_portal,
|
||||
return_contents = return_contents,
|
||||
set_jws_cookie = set_jws_cookie,
|
||||
starts_with = starts_with,
|
||||
answer_unexpected_error = answer_unexpected_error,
|
||||
with_post_parameters = with_post_parameters,
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
local util = require("ssso_util")
|
||||
local conf = require("ssso_config")
|
||||
local nginx = require("ssso_nginx")
|
||||
local prof = require("ssso_profile")
|
||||
local sites = require("ssso_sites")
|
||||
|
||||
local root = ""
|
||||
|
@ -18,14 +17,14 @@ local function contents(relative)
|
|||
end
|
||||
|
||||
local function inject_data(html, profile)
|
||||
html = html:gsub("SSSO_USER", util.str_to_html(prof.user(profile)))
|
||||
html = html:gsub("SSSO_NAME", util.str_to_html(prof.name(profile)))
|
||||
html = html:gsub("SSSO_EMAIL", util.str_to_html(prof.email(profile)))
|
||||
html = html:gsub("SSSO_USER", util.str_to_html(profile:user()))
|
||||
html = html:gsub("SSSO_NAME", util.str_to_html(profile:name()))
|
||||
html = html:gsub("SSSO_EMAIL", util.str_to_html(profile:email()))
|
||||
local links = ""
|
||||
local allowed = sites.authorized_links(prof.user(profile))
|
||||
local allowed = profile:authorized_links()
|
||||
table.sort(allowed, function(a1, a2) return a1.label < a2.label end)
|
||||
for _, allow in ipairs(allowed) do
|
||||
links = links .. '<li><a href="' .. prof.format(allow.link, profile) .. '"><span>' .. util.str_to_html(prof.format(allow.label, profile)) .. "</span></a></li>"
|
||||
links = links .. '<li><a href="' .. profile:format(allow.link) .. '"><span>' .. util.str_to_html(profile:format(allow.label)) .. "</span></a></li>"
|
||||
end
|
||||
if links ~= "" then
|
||||
html = html:gsub('<nav id="sites"></nav>', '<nav id="sites"><ul>' .. links .. "</ul></nav>")
|
||||
|
@ -37,12 +36,12 @@ end
|
|||
|
||||
local function answer_request(req_data, profile)
|
||||
local portal = conf.get_sso_prefix() .. "/portal"
|
||||
if nginx.is(req_data, portal) then
|
||||
if req_data:is(portal) then
|
||||
local html = inject_data(contents("portal.html"), profile)
|
||||
return nginx.return_contents(html, "text/html; charset=UTF-8")
|
||||
elseif nginx.is(req_data, portal .. ".css") then
|
||||
elseif req_data:is(portal .. ".css") then
|
||||
return nginx.return_contents(contents("portal.css"), "text/css; charset=UTF-8")
|
||||
elseif nginx.is(req_data, portal .. ".js") then
|
||||
elseif req_data:is(portal .. ".js") then
|
||||
return nginx.return_contents(contents("portal.js"), "application/javascript; charset=UTF-8")
|
||||
else
|
||||
return nginx.answer_not_found(req_data)
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
local b64 = require("ssso_base64")
|
||||
|
||||
local function build_profile(user, password, name, email)
|
||||
return {
|
||||
u = user,
|
||||
p = password,
|
||||
n = name,
|
||||
e = email,
|
||||
}
|
||||
end
|
||||
|
||||
local function serialize(profile)
|
||||
return (profile.u or "\025") .. "\031" ..
|
||||
(profile.p or "\025") .. "\031" ..
|
||||
(profile.n or "\025") .. "\031" ..
|
||||
(profile.e or "\025") .. "\031"
|
||||
end
|
||||
|
||||
local function deserialize(ser)
|
||||
local profile
|
||||
local remainder = ser:gsub("^(.-)\031(.-)\031(.-)\031(.-)\031", function (u, p, n, e)
|
||||
if u == "\025" then u = nil end
|
||||
if p == "\025" then p = nil end
|
||||
if n == "\025" then n = nil end
|
||||
if e == "\025" then e = nil end
|
||||
profile = build_profile(u, p, n, e)
|
||||
return ""
|
||||
end)
|
||||
return profile, remainder
|
||||
end
|
||||
|
||||
local function format(template, profile)
|
||||
local s = template
|
||||
s = s:gsub("\ru%.", profile.u or "")
|
||||
s = s:gsub("\rp%.", profile.p or "")
|
||||
s = s:gsub("\rn%.", profile.n or "")
|
||||
s = s:gsub("\re%.", profile.e or "")
|
||||
s = s:gsub("\rb64%(([^\r]-)%)%.", function(x) return b64.encode_base64(x) end)
|
||||
s = s:gsub("\ru64%(([^\r]-)%)%.", function(x) return b64.encode_base64url(x) end)
|
||||
return s
|
||||
end
|
||||
|
||||
local function email(profile)
|
||||
return profile.e
|
||||
end
|
||||
|
||||
local function name(profile)
|
||||
return profile.n
|
||||
end
|
||||
|
||||
local function user(profile)
|
||||
return profile.u
|
||||
end
|
||||
|
||||
return {
|
||||
build_profile = build_profile,
|
||||
deserialize = deserialize, -- TODO: test
|
||||
serialize = serialize, -- TODO: test
|
||||
email = email,
|
||||
format = format,
|
||||
name = name,
|
||||
user = user,
|
||||
}
|
|
@ -3,27 +3,27 @@ local login = require("ssso_login")
|
|||
local nginx = require("ssso_nginx")
|
||||
|
||||
local function get_session()
|
||||
local session, jws, tslimit
|
||||
local profile, jws, tslimit
|
||||
local user, password = nginx.get_basic_auth()
|
||||
|
||||
if user and password then
|
||||
session = login.check_credentials_and_get_profile(user, password)
|
||||
if session then
|
||||
jws, tslimit = crypto.get_jws_and_tslimit(session)
|
||||
profile = login.check_credentials_and_get_profile(user, password)
|
||||
if profile then
|
||||
jws, tslimit = crypto.get_jws_and_tslimit(profile)
|
||||
end
|
||||
end
|
||||
|
||||
if not session then
|
||||
if not profile then
|
||||
local cookie = nginx.get_jws_cookie()
|
||||
if not cookie or cookie == "" then
|
||||
return nil, 401
|
||||
end
|
||||
session, jws, tslimit = crypto.get_data_and_new_jws(cookie)
|
||||
profile, jws, tslimit = crypto.get_profile_and_new_jws(cookie)
|
||||
end
|
||||
|
||||
if session then
|
||||
if profile then
|
||||
nginx.set_jws_cookie(jws, tslimit)
|
||||
return session, 200
|
||||
return profile, 200
|
||||
else
|
||||
return nil, 403
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
local json = require("cjson.safe")
|
||||
local id = require("ssso_identity")
|
||||
local nginx = require("ssso_nginx")
|
||||
local prof = require("ssso_profile")
|
||||
|
||||
local known_private_re = {}
|
||||
local known_sites = {}
|
||||
|
@ -26,7 +26,7 @@ end
|
|||
|
||||
local function is_known_private(req_data)
|
||||
for _, r in ipairs(known_private_re) do
|
||||
if nginx.matches(req_data, r) then
|
||||
if req_data:matches(r) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
@ -37,12 +37,12 @@ local function handle_request(req_data, auth)
|
|||
if auth then
|
||||
for _, site in ipairs(auth.ok) do
|
||||
for _, r in ipairs(site.r) do
|
||||
if nginx.matches(req_data, r) then
|
||||
if req_data:matches(r) then
|
||||
for _, a in ipairs(site.a) do
|
||||
if a[1] == "C" then
|
||||
nginx.add_cookie(a[2], prof.format(a[3], auth))
|
||||
nginx.add_cookie(a[2], auth:format(a[3]))
|
||||
elseif a[1] == "H" then
|
||||
nginx.add_header(a[2], prof.format(a[3], auth))
|
||||
nginx.add_header(a[2], auth:format(a[3]))
|
||||
end
|
||||
end
|
||||
return nginx.forward_request(req_data)
|
||||
|
@ -50,7 +50,7 @@ local function handle_request(req_data, auth)
|
|||
end
|
||||
end
|
||||
for _, r in ipairs(auth.ko) do
|
||||
if nginx.matches(req_data, r) then
|
||||
if req_data:matches(r) then
|
||||
return nginx.redirect_to_login(req_data, 403)
|
||||
end
|
||||
end
|
||||
|
@ -83,12 +83,31 @@ local function format_pattern(pattern)
|
|||
return ok
|
||||
end
|
||||
|
||||
local function with_sites(profile, user)
|
||||
local class__profile = {}
|
||||
setmetatable(class__profile, {__index = id.class__identity})
|
||||
|
||||
function class__profile:build(delegate_identity, ok_list, ko_list)
|
||||
local profile = {
|
||||
delegate = delegate_identity,
|
||||
ok = ok_list,
|
||||
ko = ko_list,
|
||||
}
|
||||
setmetatable(profile, {__index = self})
|
||||
return profile
|
||||
end
|
||||
|
||||
function class__profile:build_from_lists(user, password, name, email, ok_list, ko_list)
|
||||
local delegate_identity = id.class__identity:build(user, password, name, email)
|
||||
return self:build(delegate_identity, ok_list, ko_list)
|
||||
end
|
||||
|
||||
function class__profile:build_from_conf(user, password, name, email)
|
||||
local f, site, go_on
|
||||
local ok_list = {}
|
||||
local ko_list = {}
|
||||
for _, name in ipairs(known_sites) do
|
||||
f = io.open(name, "r")
|
||||
local delegate_identity = id.class__identity:build(user, password, name, email)
|
||||
for _, known in ipairs(known_sites) do
|
||||
f = io.open(known, "r")
|
||||
if f then
|
||||
site = json.decode(f:read("*all"))
|
||||
f:close()
|
||||
|
@ -120,14 +139,28 @@ local function with_sites(profile, user)
|
|||
end
|
||||
end
|
||||
end
|
||||
profile["ok"] = ok_list
|
||||
profile["ko"] = ko_list
|
||||
return profile
|
||||
return self:build(delegate_identity, ok_list, ko_list)
|
||||
end
|
||||
|
||||
local function serialize(profile)
|
||||
function class__profile:email()
|
||||
return self.delegate:email()
|
||||
end
|
||||
|
||||
function class__profile:name()
|
||||
return self.delegate:name()
|
||||
end
|
||||
|
||||
function class__profile:user()
|
||||
return self.delegate:user()
|
||||
end
|
||||
|
||||
function class__profile:format(template)
|
||||
return self.delegate:format(template)
|
||||
end
|
||||
|
||||
function class__profile:serialize()
|
||||
local ser_s = ""
|
||||
for _, site in ipairs(profile.ok or {}) do
|
||||
for _, site in ipairs(self.ok or {}) do
|
||||
for _, r in ipairs(site.r) do
|
||||
ser_s = ser_s .. r .. "\029"
|
||||
end
|
||||
|
@ -136,40 +169,40 @@ local function serialize(profile)
|
|||
end
|
||||
ser_s = ser_s .. "\031"
|
||||
end
|
||||
for _, r in ipairs(profile.ko or {}) do
|
||||
for _, r in ipairs(self.ko or {}) do
|
||||
ser_s = ser_s .. r .. "\030"
|
||||
end
|
||||
return ser_s
|
||||
return ser_s .. "\026" .. self.delegate:serialize()
|
||||
end
|
||||
|
||||
local function deserialize_update(ser, profile)
|
||||
if not ser or ser == "" then
|
||||
return profile
|
||||
end
|
||||
function class__profile:deserialize(ser)
|
||||
local ok_list = {}
|
||||
local ko_list = {}
|
||||
local remainder = ser:gsub("(.-)\031", function (ser_ok)
|
||||
local ok = {
|
||||
r = {},
|
||||
a = {},
|
||||
}
|
||||
ser_ok = ser_ok:gsub("(.-)\029", function(r) table.insert(ok.r, r); return "" end)
|
||||
ser_ok:gsub("(.)([^=]-)=(.-)\028", function(t, n, v) table.insert(ok.a, {t, n, v}) end)
|
||||
table.insert(ok_list, ok)
|
||||
ser = ser:gsub("^(.-)\026", function (ser_sites)
|
||||
ser_sites = ser_sites:gsub("(.-)\031", function (ser_ok)
|
||||
local ok = {
|
||||
r = {},
|
||||
a = {},
|
||||
}
|
||||
ser_ok = ser_ok:gsub("(.-)\029", function(r) table.insert(ok.r, r); return "" end)
|
||||
ser_ok:gsub("(.)([^=]-)=(.-)\028", function(t, n, v) table.insert(ok.a, {t, n, v}) end)
|
||||
table.insert(ok_list, ok)
|
||||
return ""
|
||||
end)
|
||||
ser_sites = ser_sites:gsub("(.-)\030", function (ko)
|
||||
table.insert(ko_list, ko)
|
||||
return ""
|
||||
end)
|
||||
return ""
|
||||
end)
|
||||
remainder = remainder:gsub("(.-)\030", function (ko)
|
||||
table.insert(ko_list, ko)
|
||||
return ""
|
||||
end)
|
||||
profile.ok = ok_list
|
||||
profile.ko = ko_list
|
||||
return profile, remainder
|
||||
local delegate_identity = id.class__identity:deserialize(ser)
|
||||
return self:build(delegate_identity, ok_list, ko_list)
|
||||
end
|
||||
|
||||
local function authorized_links(user)
|
||||
function class__profile:authorized_links()
|
||||
local links = {}
|
||||
local f, site, go_on
|
||||
local user = self:user()
|
||||
for _, name in ipairs(known_sites) do
|
||||
f = io.open(name, "r")
|
||||
if f then
|
||||
|
@ -206,10 +239,7 @@ local function authorized_links(user)
|
|||
end
|
||||
|
||||
return {
|
||||
authorized_links = authorized_links,
|
||||
deserialize_update = deserialize_update, -- TODO: test
|
||||
class__profile = class__profile,
|
||||
handle_request = handle_request,
|
||||
load_sites = load_sites,
|
||||
serialize = serialize, -- TODO: test
|
||||
with_sites = with_sites,
|
||||
}
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
local lu = require("luaunit")
|
||||
local conf = require("ssso_config")
|
||||
local crypt = require("ssso_crypto")
|
||||
local sites = require("ssso_sites")
|
||||
|
||||
local here = debug.getinfo(1).source:sub(2, -18)
|
||||
conf.load_conf(here)
|
||||
|
||||
local data = {
|
||||
u = "u",
|
||||
e = "u@h",
|
||||
ok = {
|
||||
local data = sites.class__profile:build_from_lists("u", nil, nil, "u@h",
|
||||
{
|
||||
{
|
||||
r = {
|
||||
"regex1",
|
||||
|
@ -19,10 +18,10 @@ local data = {
|
|||
}
|
||||
},
|
||||
},
|
||||
ko = {
|
||||
{
|
||||
"regex2",
|
||||
},
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
function test_jws_is_well_structured()
|
||||
local jws, _ = crypt.get_jws_and_tslimit(data)
|
||||
|
@ -31,17 +30,12 @@ end
|
|||
|
||||
function test_jws_can_be_decoded()
|
||||
local jws, _ = crypt.get_jws_and_tslimit(data)
|
||||
local stored, _, _ = crypt.get_data_and_new_jws(jws)
|
||||
local stored, _, _ = crypt.get_profile_and_new_jws(jws)
|
||||
lu.assertEquals(stored, data)
|
||||
end
|
||||
|
||||
function test_data_must_contain_field_u()
|
||||
local wrong = {
|
||||
i = 1,
|
||||
f = 2.3,
|
||||
b = true,
|
||||
n = nil,
|
||||
}
|
||||
function test_data_must_be_a_profile_with_a_user()
|
||||
local wrong = sites.class__profile:build_from_conf(nil, "P", "N", "E")
|
||||
local jws, ts = crypt.get_jws_and_tslimit(wrong)
|
||||
lu.assertNil(jws)
|
||||
lu.assertNil(ts)
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
local lu = require("luaunit")
|
||||
local id = require("ssso_identity")
|
||||
|
||||
function test_format_replaces_user_placeholders()
|
||||
local identity = id.class__identity:build("U", nil, nil, nil)
|
||||
local template = '{user: "\ru.", foo: "bar", name: "\ru."}'
|
||||
lu.assertEquals(identity:format(template), '{user: "U", foo: "bar", name: "U"}')
|
||||
end
|
||||
|
||||
function test_format_replaces_password_placeholders()
|
||||
local identity = id.class__identity:build(nil, "P", nil, nil)
|
||||
local template = '{pass: "\rp.", foo: "bar", secret: "\rp."}'
|
||||
lu.assertEquals(identity:format(template), '{pass: "P", foo: "bar", secret: "P"}')
|
||||
end
|
||||
|
||||
function test_format_replaces_name_placeholders()
|
||||
local identity = id.class__identity:build(nil, nil, "N", nil)
|
||||
local template = '{name: "\rn.", foo: "bar", nickname: "\rn."}'
|
||||
lu.assertEquals(identity:format(template), '{name: "N", foo: "bar", nickname: "N"}')
|
||||
end
|
||||
|
||||
function test_format_replaces_email_placeholders()
|
||||
local identity = id.class__identity:build(nil, nil, nil, "user@host")
|
||||
local template = '{user: "\re.", foo: "bar", mail: "\re."}'
|
||||
lu.assertEquals(identity:format(template), '{user: "user@host", foo: "bar", mail: "user@host"}')
|
||||
end
|
||||
|
||||
function test_format_replaces_base64_calls()
|
||||
local identity = id.class__identity:build("👤", "🔒", nil, nil)
|
||||
local template = 'Authorization: Basic \rb64(\ru.:\rp.).'
|
||||
lu.assertEquals(identity:format(template), 'Authorization: Basic 8J+RpDrwn5SS')
|
||||
end
|
||||
|
||||
function test_format_replaces_base64url_calls()
|
||||
local identity = id.class__identity:build("👤", "🔒", nil, nil)
|
||||
local template = '?authorization=Basic+\ru64(\ru.:\rp.).'
|
||||
lu.assertEquals(identity:format(template), '?authorization=Basic+8J-RpDrwn5SS')
|
||||
end
|
||||
|
||||
function test_email_returns_the_identity_s_email()
|
||||
local identity = id.class__identity:build(nil, nil, nil, "E")
|
||||
lu.assertEquals(identity:email(), "E")
|
||||
end
|
||||
|
||||
|
||||
function test_name_returns_the_identity_s_name()
|
||||
local identity = id.class__identity:build(nil, nil, "N", nil)
|
||||
lu.assertEquals(identity:name(), "N")
|
||||
end
|
||||
|
||||
|
||||
function test_user_returns_the_identity_s_user()
|
||||
local identity = id.class__identity:build("U", nil, nil, nil)
|
||||
lu.assertEquals(identity:user(), "U")
|
||||
end
|
||||
|
||||
function test_build_identity_returns_the_given_information()
|
||||
lu.assertEquals(id.class__identity:build("U", "P", "N", "E"), {u = "U", p = "P", n = "N", e = "E"})
|
||||
end
|
||||
|
||||
os.exit(lu.LuaUnit.run())
|
|
@ -15,7 +15,7 @@ function test_get_login_url_returns_html_with_back_url_substitution()
|
|||
ngx.reset_resp_body()
|
||||
ngx.var.request_method = "GET"
|
||||
ngx.var.request_uri = "/ssso/login?back=/somewhere"
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
local expected = [[<html><head>
|
||||
<link href="login.css">
|
||||
<script src="login.js"></script>
|
||||
|
@ -40,7 +40,7 @@ function test_login_css_url_returns_css()
|
|||
ngx.reset_resp_body()
|
||||
ngx.var.request_method = "BLABLA"
|
||||
ngx.var.request_uri = "/ssso/login.css"
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
local expected = "/*CSS*/\n"
|
||||
-- when
|
||||
local resp = login.answer_request(r)
|
||||
|
@ -58,7 +58,7 @@ function test_login_js_url_returns_js()
|
|||
ngx.reset_resp_body()
|
||||
ngx.var.request_method = "BLABLA"
|
||||
ngx.var.request_uri = "/ssso/login.js"
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
local expected = "//JS\n"
|
||||
-- when
|
||||
local resp = login.answer_request(r)
|
||||
|
@ -75,7 +75,7 @@ function test_unknown_login_url_returns_404()
|
|||
ngx.reset_resp_body()
|
||||
ngx.var.request_method = "BLABLA"
|
||||
ngx.var.request_uri = "/ssso/login/unknown"
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
-- when
|
||||
local resp = login.answer_request(r)
|
||||
-- then
|
||||
|
@ -90,7 +90,7 @@ function test_get_login_url_with_cause_401_returns_html_with_associated_message(
|
|||
ngx.reset_resp_body()
|
||||
ngx.var.request_method = "GET"
|
||||
ngx.var.request_uri = "/ssso/login?cause=401"
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
local expected = [[<html><head>
|
||||
<link href="login.css">
|
||||
<script src="login.js"></script>
|
||||
|
@ -115,7 +115,7 @@ function test_get_login_url_with_cause_403_returns_html_with_associated_message(
|
|||
ngx.reset_resp_body()
|
||||
ngx.var.request_method = "GET"
|
||||
ngx.var.request_uri = "/ssso/login?cause=403"
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
local expected = [[<html><head>
|
||||
<link href="login.css">
|
||||
<script src="login.js"></script>
|
||||
|
@ -141,7 +141,7 @@ function test_post_login_url_with_wrong_credentials_returns_html_with_associated
|
|||
ngx.reset_post_var()
|
||||
ngx.var.request_method = "POST"
|
||||
ngx.var.request_uri = "/ssso/login"
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
local expected = [[<html><head>
|
||||
<link href="login.css">
|
||||
<script src="login.js"></script>
|
||||
|
@ -169,7 +169,7 @@ function test_post_login_url_with_good_credentials_redirects_to_portal_with_sess
|
|||
ngx.var.request_uri = "/ssso/login"
|
||||
ngx.post_var.login = "goodlogin"
|
||||
ngx.post_var.password = "goodpassword"
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
-- when
|
||||
local resp = login.answer_request(r)
|
||||
-- then
|
||||
|
@ -190,7 +190,7 @@ function test_post_login_url_with_good_credentials_and_back_url_redirects_to_giv
|
|||
ngx.post_var.login = "goodlogin"
|
||||
ngx.post_var.password = "goodpassword"
|
||||
ngx.post_var.back = "/somewhere"
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
-- when
|
||||
local resp = login.answer_request(r)
|
||||
-- then
|
||||
|
|
|
@ -15,7 +15,7 @@ function test_refe_host_meth_uri_taken_from_ngx()
|
|||
ngx.var.request_method = "M"
|
||||
ngx.var.request_uri = "U"
|
||||
-- when
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
-- then
|
||||
lu.assertEquals(r.referer, "R")
|
||||
lu.assertEquals(r.host, "H")
|
||||
|
@ -31,7 +31,7 @@ function test_empty_referer_reported_as_nil()
|
|||
ngx.var.request_uri = "U"
|
||||
ngx.var.http_referer = ""
|
||||
-- when
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
-- then
|
||||
lu.assertEquals(r.referer, nil)
|
||||
end
|
||||
|
@ -41,7 +41,7 @@ function test_query_params_split_from_uri_and_decoded()
|
|||
ngx.reset_var()
|
||||
ngx.var.request_uri = "U?P=V&Q=W"
|
||||
-- when
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
-- then
|
||||
lu.assertEquals(r.uri, "U?P=V&Q=W")
|
||||
lu.assertEquals(r.target, "U")
|
||||
|
@ -53,7 +53,7 @@ function test_default_scheme_is_http()
|
|||
ngx.reset_var()
|
||||
ngx.var.request_uri = "U"
|
||||
-- when
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
-- then
|
||||
lu.assertEquals(r.scheme, "http")
|
||||
end
|
||||
|
@ -64,7 +64,7 @@ function test_scheme_is_https_when_proxy_https_var()
|
|||
ngx.var.request_uri = "U"
|
||||
ngx.var.proxy_https = 1
|
||||
-- when
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
-- then
|
||||
lu.assertEquals(r.scheme, "https")
|
||||
end
|
||||
|
@ -75,7 +75,7 @@ function test_scheme_is_https_when_https_var()
|
|||
ngx.var.request_uri = "U"
|
||||
ngx.var.https = 1
|
||||
-- when
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
-- then
|
||||
lu.assertEquals(r.scheme, "https")
|
||||
end
|
||||
|
@ -142,10 +142,10 @@ function test_method_is_recognized_case_insensitive()
|
|||
ngx.reset_var()
|
||||
ngx.var.request_method = "get"
|
||||
ngx.var.request_uri = "U"
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
-- when
|
||||
local is_get = ng.has_method(r, "GET")
|
||||
local is_post = ng.has_method(r, "POST")
|
||||
local is_get = r:has_method("GET")
|
||||
local is_post = r:has_method("POST")
|
||||
-- then
|
||||
lu.assertTrue(is_get and true)
|
||||
lu.assertFalse(is_post or false)
|
||||
|
@ -155,10 +155,10 @@ function test_uri_identity_ignores_query_parameters()
|
|||
-- given
|
||||
ngx.reset_var()
|
||||
ngx.var.request_uri = "U?P=V&Q=W"
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
-- when
|
||||
local is_without_qp = ng.is(r, "U")
|
||||
local is_with_qp = ng.is(r, "U?P=V&Q=W")
|
||||
local is_without_qp = r:is("U")
|
||||
local is_with_qp = r:is("U?P=V&Q=W")
|
||||
-- then
|
||||
lu.assertTrue(is_without_qp and true)
|
||||
lu.assertFalse(is_with_qp or false)
|
||||
|
@ -168,10 +168,10 @@ function test_uri_match_ignores_query_parameters()
|
|||
-- given
|
||||
ngx.reset_var()
|
||||
ngx.var.request_uri = "/aa?bb"
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
-- when
|
||||
local matches_without_qp = ng.matches(r, "/a+$")
|
||||
local matches_with_qp = ng.matches(r, "/a.*b")
|
||||
local matches_without_qp = r:matches("/a+$")
|
||||
local matches_with_qp = r:matches("/a.*b")
|
||||
-- then
|
||||
lu.assertTrue(matches_without_qp and true)
|
||||
lu.assertFalse(matches_with_qp or false)
|
||||
|
@ -181,10 +181,10 @@ function test_starts_with_ignores_query_parameters()
|
|||
-- given
|
||||
ngx.reset_var()
|
||||
ngx.var.request_uri = "/aa?bb"
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
-- when
|
||||
local start_without_qp = ng.starts_with(r, "/a")
|
||||
local start_with_qp = ng.starts_with(r, "/aa?b")
|
||||
local start_without_qp = r:starts_with("/a")
|
||||
local start_with_qp = r:starts_with("/aa?b")
|
||||
-- then
|
||||
lu.assertTrue(start_without_qp and true)
|
||||
lu.assertFalse(start_with_qp or false)
|
||||
|
@ -194,10 +194,10 @@ function test_starts_with_must_start_with_given_value()
|
|||
-- given
|
||||
ngx.reset_var()
|
||||
ngx.var.request_uri = "/aa?bb"
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
-- when
|
||||
local start_in_middle = ng.starts_with(r, "aa")
|
||||
local does_not_start = ng.starts_with(r, "x")
|
||||
local start_in_middle = r:starts_with("aa")
|
||||
local does_not_start = r:starts_with("x")
|
||||
-- then
|
||||
lu.assertFalse(start_in_middle or false)
|
||||
lu.assertFalse(does_not_start or false)
|
||||
|
@ -207,11 +207,11 @@ function test_has_param_works_disregarding_the_value()
|
|||
-- given
|
||||
ngx.reset_var()
|
||||
ngx.var.request_uri = "/aa?bb&c=1"
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
-- when
|
||||
local has_unknown_param = ng.has_param(r, "b")
|
||||
local has_unvalued_param = ng.has_param(r, "bb")
|
||||
local has_valued_param = ng.has_param(r, "c")
|
||||
local has_unknown_param = r:has_param("b")
|
||||
local has_unvalued_param = r:has_param("bb")
|
||||
local has_valued_param = r:has_param("c")
|
||||
-- then
|
||||
lu.assertFalse(has_unknown_param or false)
|
||||
lu.assertTrue(has_unvalued_param and true)
|
||||
|
@ -222,10 +222,10 @@ function test_has_param_works_with_a_correct_value()
|
|||
-- given
|
||||
ngx.reset_var()
|
||||
ngx.var.request_uri = "/aa?bb&c=1"
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
-- when
|
||||
local has_unvalued_param = ng.has_param(r, "bb", true)
|
||||
local has_valued_param = ng.has_param(r, "c", "1")
|
||||
local has_unvalued_param = r:has_param("bb", true)
|
||||
local has_valued_param = r:has_param("c", "1")
|
||||
-- then
|
||||
lu.assertTrue(has_unvalued_param and true)
|
||||
lu.assertTrue(has_valued_param and true)
|
||||
|
@ -235,11 +235,11 @@ function test_has_param_works_with_a_wrong_value()
|
|||
-- given
|
||||
ngx.reset_var()
|
||||
ngx.var.request_uri = "/aa?bb&c=1"
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
-- when
|
||||
local has_unknown_param = ng.has_param(r, "b", "x")
|
||||
local has_unvalued_param = ng.has_param(r, "bb", "x")
|
||||
local has_valued_param = ng.has_param(r, "c", "x")
|
||||
local has_unknown_param = r:has_param("b", "x")
|
||||
local has_unvalued_param = r:has_param("bb", "x")
|
||||
local has_valued_param = r:has_param("c", "x")
|
||||
-- then
|
||||
lu.assertFalse(has_unknown_param or false)
|
||||
lu.assertFalse(has_unvalued_param or false)
|
||||
|
@ -284,7 +284,7 @@ function test_with_post_parameters_merges_post_parameters_to_request_data()
|
|||
ngx.post_var.p = "5"
|
||||
ngx.post_var.r = "hello"
|
||||
-- when (1)
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
-- then (1)
|
||||
lu.assertEquals(r, {
|
||||
scheme = "http",
|
||||
|
@ -296,7 +296,7 @@ function test_with_post_parameters_merges_post_parameters_to_request_data()
|
|||
},
|
||||
})
|
||||
-- when (2)
|
||||
r = ng.with_post_parameters(r)
|
||||
r = r:with_post_parameters()
|
||||
-- then (2)
|
||||
lu.assertEquals(r, {
|
||||
scheme = "http",
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
local lu = require("luaunit")
|
||||
local ngx = require("ngx")
|
||||
local crypto = require("ssso_crypto")
|
||||
local sites = require("ssso_sites")
|
||||
|
||||
require("do_init")
|
||||
|
||||
function test_portal_url_returns_html_with_authorized_links_and_identity()
|
||||
-- given
|
||||
local jws, _ = crypto.get_jws_and_tslimit({
|
||||
u = "guest",
|
||||
p = "",
|
||||
n = "Guest",
|
||||
e = "guest@example.org",
|
||||
})
|
||||
local profile = sites.class__profile:build_from_lists("guest", "", "Guest", "guest@example.org")
|
||||
local jws, _ = crypto.get_jws_and_tslimit(profile)
|
||||
ngx.reset_resp_body()
|
||||
ngx.reset_var()
|
||||
ngx.var.cookie_SSSO_TOKEN = jws
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
local lu = require("luaunit")
|
||||
local ngx = require("ngx")
|
||||
local crypto = require("ssso_crypto")
|
||||
local sites = require("ssso_sites")
|
||||
|
||||
require("do_init")
|
||||
|
||||
function test_portal_css_url_returns_css()
|
||||
-- given
|
||||
local jws, _ = crypto.get_jws_and_tslimit({u = "U", p = "P", n = "N", e = "u@h"})
|
||||
local profile = sites.class__profile:build_from_lists("U", "P", "N", "u@h")
|
||||
local jws, _ = crypto.get_jws_and_tslimit(profile)
|
||||
ngx.reset_resp_body()
|
||||
ngx.reset_var()
|
||||
ngx.var.cookie_SSSO_TOKEN = jws
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
local lu = require("luaunit")
|
||||
local ngx = require("ngx")
|
||||
local crypto = require("ssso_crypto")
|
||||
local sites = require("ssso_sites")
|
||||
|
||||
require("do_init")
|
||||
|
||||
function test_portal_js_url_returns_js()
|
||||
-- given
|
||||
local jws, _ = crypto.get_jws_and_tslimit({u = "U", p = "P", n = "N", e = "u@h"})
|
||||
local profile = sites.class__profile:build_from_lists("U", "P", "N", "u@h")
|
||||
local jws, _ = crypto.get_jws_and_tslimit(profile)
|
||||
ngx.reset_resp_body()
|
||||
ngx.reset_var()
|
||||
ngx.var.cookie_SSSO_TOKEN = jws
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
local lu = require("luaunit")
|
||||
local ngx = require("ngx")
|
||||
local crypto = require("ssso_crypto")
|
||||
local sites = require("ssso_sites")
|
||||
|
||||
require("do_init")
|
||||
|
||||
function test_unknown_portal_url_returns_404()
|
||||
-- given
|
||||
local jws, _ = crypto.get_jws_and_tslimit({u = "U", p = "P", n = "N", e = "u@h"})
|
||||
local profile = sites.class__profile:build_from_lists("U", "P", "N", "u@h")
|
||||
local jws, _ = crypto.get_jws_and_tslimit(profile)
|
||||
ngx.reset_resp_body()
|
||||
ngx.reset_var()
|
||||
ngx.var.cookie_SSSO_TOKEN = jws
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
local lu = require("luaunit")
|
||||
local ngx = require("ngx")
|
||||
local crypto = require("ssso_crypto")
|
||||
|
||||
require("do_init")
|
||||
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
local lu = require("luaunit")
|
||||
local prf = require("ssso_profile")
|
||||
|
||||
function test_format_replaces_user_placeholders()
|
||||
local profile = {
|
||||
u = "U",
|
||||
}
|
||||
local template = '{user: "\ru.", foo: "bar", name: "\ru."}'
|
||||
lu.assertEquals(prf.format(template, profile), '{user: "U", foo: "bar", name: "U"}')
|
||||
end
|
||||
|
||||
function test_format_replaces_password_placeholders()
|
||||
local profile = {
|
||||
p = "P",
|
||||
}
|
||||
local template = '{pass: "\rp.", foo: "bar", secret: "\rp."}'
|
||||
lu.assertEquals(prf.format(template, profile), '{pass: "P", foo: "bar", secret: "P"}')
|
||||
end
|
||||
|
||||
function test_format_replaces_name_placeholders()
|
||||
local profile = {
|
||||
n = "N",
|
||||
}
|
||||
local template = '{name: "\rn.", foo: "bar", nickname: "\rn."}'
|
||||
lu.assertEquals(prf.format(template, profile), '{name: "N", foo: "bar", nickname: "N"}')
|
||||
end
|
||||
|
||||
function test_format_replaces_email_placeholders()
|
||||
local profile = {
|
||||
e = "user@host",
|
||||
}
|
||||
local template = '{user: "\re.", foo: "bar", mail: "\re."}'
|
||||
lu.assertEquals(prf.format(template, profile), '{user: "user@host", foo: "bar", mail: "user@host"}')
|
||||
end
|
||||
|
||||
function test_format_replaces_base64_calls()
|
||||
local profile = {
|
||||
u = "👤",
|
||||
p = "🔒",
|
||||
}
|
||||
local template = 'Authorization: Basic \rb64(\ru.:\rp.).'
|
||||
lu.assertEquals(prf.format(template, profile), 'Authorization: Basic 8J+RpDrwn5SS')
|
||||
end
|
||||
|
||||
function test_format_replaces_base64url_calls()
|
||||
local profile = {
|
||||
u = "👤",
|
||||
p = "🔒",
|
||||
}
|
||||
local template = '?authorization=Basic+\ru64(\ru.:\rp.).'
|
||||
lu.assertEquals(prf.format(template, profile), '?authorization=Basic+8J-RpDrwn5SS')
|
||||
end
|
||||
|
||||
function test_email_returns_the_profile_s_email()
|
||||
local profile = {
|
||||
e = "E",
|
||||
}
|
||||
lu.assertEquals(prf.email(profile), "E")
|
||||
end
|
||||
|
||||
|
||||
function test_name_returns_the_profile_s_name()
|
||||
local profile = {
|
||||
n = "N",
|
||||
}
|
||||
lu.assertEquals(prf.name(profile), "N")
|
||||
end
|
||||
|
||||
|
||||
function test_user_returns_the_profile_s_user()
|
||||
local profile = {
|
||||
u = "U",
|
||||
}
|
||||
lu.assertEquals(prf.user(profile), "U")
|
||||
end
|
||||
|
||||
function test_build_profile_returns_the_given_information()
|
||||
lu.assertEquals(prf.build_profile("U", "P", "N", "E"), {u = "U", p = "P", n = "N", e = "E"})
|
||||
end
|
||||
|
||||
os.exit(lu.LuaUnit.run())
|
|
@ -51,13 +51,13 @@ function test_session_and_cookie_renewal_if_good_cookie()
|
|||
ngx.req.reset()
|
||||
ngx.reset_header()
|
||||
ngx.reset_var()
|
||||
local data = {u = "bob"}
|
||||
local c, _ = crypt.get_jws_and_tslimit(data)
|
||||
local profile = sites.class__profile:build_from_lists("bob", nil, nil, nil, {}, {})
|
||||
local c, _ = crypt.get_jws_and_tslimit(profile)
|
||||
ngx.var.cookie_SSSO_TOKEN = c
|
||||
-- when
|
||||
local s, h = sess.get_session()
|
||||
-- then
|
||||
lu.assertEquals(s, data)
|
||||
lu.assertEquals(s, profile)
|
||||
lu.assertEquals(h, 200)
|
||||
lu.assertNil(ngx.header["Set-Cookie"].link)
|
||||
lu.assertStrMatches(ngx.header["Set-Cookie"].v, "SSSO_TOKEN=[^%.]+%.[^%.]+%.[^%.]+; Path=/; Expires=1626550390; Secure")
|
||||
|
@ -84,15 +84,15 @@ function test_basic_auth_takes_precedence_over_cookie()
|
|||
ngx.req.reset()
|
||||
ngx.reset_header()
|
||||
ngx.reset_var()
|
||||
local data = {u = "forget me"}
|
||||
local c, _ = crypt.get_jws_and_tslimit(data)
|
||||
local profile = sites.class__profile:build_from_lists("forget me", nil, nil, nil, {}, {})
|
||||
local c, _ = crypt.get_jws_and_tslimit(profile)
|
||||
ngx.var.cookie_SSSO_TOKEN = c
|
||||
ngx.var.Authentication = "Basic " .. b64.encode_base64("bob:goodpassword")
|
||||
-- when
|
||||
local s, h = sess.get_session()
|
||||
-- then
|
||||
lu.assertEquals(h, 200)
|
||||
lu.assertEquals(s.u, "bob")
|
||||
lu.assertEquals(s:user(), "bob")
|
||||
lu.assertNil(ngx.header["Set-Cookie"].link)
|
||||
lu.assertStrMatches(ngx.header["Set-Cookie"].v, "SSSO_TOKEN=[^%.]+%.[^%.]+%.[^%.]+; Path=/; Expires=1626550390; Secure")
|
||||
end
|
||||
|
@ -102,15 +102,15 @@ function test_basic_auth_ignored_if_invalid()
|
|||
ngx.req.reset()
|
||||
ngx.reset_header()
|
||||
ngx.reset_var()
|
||||
local data = {u = "do not forget me"}
|
||||
local c, _ = crypt.get_jws_and_tslimit(data)
|
||||
local profile = sites.class__profile:build_from_lists("do not forget me", nil, nil, nil, {}, {})
|
||||
local c, _ = crypt.get_jws_and_tslimit(profile)
|
||||
ngx.var.cookie_SSSO_TOKEN = c
|
||||
ngx.var.Authentication = "Basic !!!!"
|
||||
-- when
|
||||
local s, h = sess.get_session()
|
||||
-- then
|
||||
lu.assertEquals(h, 200)
|
||||
lu.assertEquals(s.u, "do not forget me")
|
||||
lu.assertEquals(s:user(), "do not forget me")
|
||||
lu.assertNil(ngx.header["Set-Cookie"].link)
|
||||
lu.assertStrMatches(ngx.header["Set-Cookie"].v, "SSSO_TOKEN=[^%.]+%.[^%.]+%.[^%.]+; Path=/; Expires=1626550390; Secure")
|
||||
end
|
||||
|
|
|
@ -13,7 +13,7 @@ function test_anonymous_access_to_unknown_site_accepted()
|
|||
ngx.req.reset()
|
||||
ngx.reset_var()
|
||||
ngx.var.request_uri = "/unknown"
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
-- when
|
||||
local resp = sites.handle_request(r, nil)
|
||||
-- then
|
||||
|
@ -26,7 +26,7 @@ function test_anonymous_access_to_public_site_accepted()
|
|||
ngx.req.reset()
|
||||
ngx.reset_var()
|
||||
ngx.var.request_uri = "/public/page"
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
-- when
|
||||
local resp = sites.handle_request(r, nil)
|
||||
-- then
|
||||
|
@ -39,7 +39,7 @@ function test_anonymous_access_to_public_page_of_mixed_site_accepted()
|
|||
ngx.req.reset()
|
||||
ngx.reset_var()
|
||||
ngx.var.request_uri = "/mixed/bob/wiki/foo.adoc"
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
-- when
|
||||
local resp = sites.handle_request(r, nil)
|
||||
-- then
|
||||
|
@ -52,7 +52,7 @@ function test_anonymous_access_to_private_page_of_mixed_site_redirected_401()
|
|||
ngx.req.reset()
|
||||
ngx.reset_var()
|
||||
ngx.var.request_uri = "/mixed/bob/wiki/_new"
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
-- when
|
||||
local resp = sites.handle_request(r, nil)
|
||||
-- then
|
||||
|
@ -65,7 +65,7 @@ function test_anonymous_access_to_private_site_redirected_401()
|
|||
ngx.req.reset()
|
||||
ngx.reset_var()
|
||||
ngx.var.request_uri = "/private/page"
|
||||
local r = ng.get_request()
|
||||
local r = ng.class__request:current()
|
||||
-- when
|
||||
local resp = sites.handle_request(r, nil)
|
||||
-- then
|
||||
|
@ -78,12 +78,8 @@ function test_authenticated_access_to_unknown_site_accepted()
|
|||
ngx.req.reset()
|
||||
ngx.reset_var()
|
||||
ngx.var.request_uri = "/unknown"
|
||||
local r = ng.get_request()
|
||||
local profile = {
|
||||
u = "U",
|
||||
ok = {},
|
||||
ko = {},
|
||||
}
|
||||
local r = ng.class__request:current()
|
||||
local profile = sites.class__profile:build_from_lists("U", nil, nil, nil, {}, {})
|
||||
-- when
|
||||
local resp = sites.handle_request(r, profile)
|
||||
-- then
|
||||
|
@ -96,11 +92,9 @@ function test_authenticated_access_to_public_site_accepted()
|
|||
ngx.req.reset()
|
||||
ngx.reset_var()
|
||||
ngx.var.request_uri = "/public/page"
|
||||
local r = ng.get_request()
|
||||
local profile = {
|
||||
u = "U",
|
||||
p = "P",
|
||||
ok = {
|
||||
local r = ng.class__request:current()
|
||||
local profile = sites.class__profile:build_from_lists("U", "P", nil, nil,
|
||||
{
|
||||
{
|
||||
r = {
|
||||
"^/public",
|
||||
|
@ -110,8 +104,9 @@ function test_authenticated_access_to_public_site_accepted()
|
|||
{"C", "X-PROXY-PASS", "\rp."},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
{}
|
||||
)
|
||||
-- when
|
||||
local resp = sites.handle_request(r, profile)
|
||||
-- then
|
||||
|
@ -125,14 +120,13 @@ function test_authenticated_access_to_public_site_can_be_denied()
|
|||
ngx.req.reset()
|
||||
ngx.reset_var()
|
||||
ngx.var.request_uri = "/public/page"
|
||||
local r = ng.get_request()
|
||||
local profile = {
|
||||
u = "banned",
|
||||
ok = {},
|
||||
ko = {
|
||||
local r = ng.class__request:current()
|
||||
local profile = sites.class__profile:build_from_lists("banned", nil, nil, nil,
|
||||
{},
|
||||
{
|
||||
"^/public",
|
||||
}
|
||||
}
|
||||
)
|
||||
-- when
|
||||
local resp = sites.handle_request(r, profile)
|
||||
-- then
|
||||
|
@ -145,11 +139,9 @@ function test_authenticated_access_to_public_page_of_mixed_site_accepted()
|
|||
ngx.req.reset()
|
||||
ngx.reset_var()
|
||||
ngx.var.request_uri = "/mixed/bob/wiki/foo.adoc"
|
||||
local r = ng.get_request()
|
||||
local profile = {
|
||||
u = "U",
|
||||
p = "P",
|
||||
ok = {
|
||||
local r = ng.class__request:current()
|
||||
local profile = sites.class__profile:build_from_lists("U", "P", nil, nil,
|
||||
{
|
||||
{
|
||||
r = {
|
||||
"^/public",
|
||||
|
@ -179,8 +171,9 @@ function test_authenticated_access_to_public_page_of_mixed_site_accepted()
|
|||
{"C", "X-PROXY-PASSWORD", "\rp."},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
{}
|
||||
)
|
||||
-- when
|
||||
local resp = sites.handle_request(r, profile)
|
||||
-- then
|
||||
|
@ -194,11 +187,9 @@ function test_authenticated_access_to_private_page_of_mixed_site_accepted()
|
|||
ngx.req.reset()
|
||||
ngx.reset_var()
|
||||
ngx.var.request_uri = "/mixed/bob/wiki/_new"
|
||||
local r = ng.get_request()
|
||||
local profile = {
|
||||
u = "U",
|
||||
p = "P",
|
||||
ok = {
|
||||
local r = ng.class__request:current()
|
||||
local profile = sites.class__profile:build_from_lists("U", "P", nil, nil,
|
||||
{
|
||||
{
|
||||
r = {
|
||||
"^/public",
|
||||
|
@ -228,8 +219,9 @@ function test_authenticated_access_to_private_page_of_mixed_site_accepted()
|
|||
{"C", "X-PROXY-PASSWORD", "\rp."},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
{}
|
||||
)
|
||||
-- when
|
||||
local resp = sites.handle_request(r, profile)
|
||||
-- then
|
||||
|
@ -243,11 +235,9 @@ function test_authenticated_access_to_private_site_accepted_with_the_right_user(
|
|||
ngx.req.reset()
|
||||
ngx.reset_var()
|
||||
ngx.var.request_uri = "/private/page"
|
||||
local r = ng.get_request()
|
||||
local profile = {
|
||||
u = "jean",
|
||||
p = "P",
|
||||
ok = {
|
||||
local r = ng.class__request:current()
|
||||
local profile = sites.class__profile:build_from_lists("jean", "P", nil, nil,
|
||||
{
|
||||
{
|
||||
r = {
|
||||
"^/private",
|
||||
|
@ -256,8 +246,9 @@ function test_authenticated_access_to_private_site_accepted_with_the_right_user(
|
|||
{"H", "Authorization", "Basic \rb64(\ru.:\rp.)."},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
{}
|
||||
)
|
||||
-- when
|
||||
local resp = sites.handle_request(r, profile)
|
||||
-- then
|
||||
|
@ -270,15 +261,13 @@ function test_authenticated_access_to_private_site_redirected_403_with_the_wrong
|
|||
ngx.req.reset()
|
||||
ngx.reset_var()
|
||||
ngx.var.request_uri = "/private/page"
|
||||
local r = ng.get_request()
|
||||
local profile = {
|
||||
u = "U",
|
||||
p = "P",
|
||||
ok = {},
|
||||
ko = {
|
||||
local r = ng.class__request:current()
|
||||
local profile = sites.class__profile:build_from_lists("U", "P", nil, nil,
|
||||
{},
|
||||
{
|
||||
"^/private",
|
||||
}
|
||||
}
|
||||
)
|
||||
-- when
|
||||
local resp = sites.handle_request(r, profile)
|
||||
-- then
|
||||
|
|
Loading…
Reference in New Issue