mirror of
https://github.com/YunoHost/SSOwat.git
synced 2024-09-03 20:06:27 +02:00
Merge pull request #161 from YunoHost/permission_protection
[WIP] Rework permissions
This commit is contained in:
commit
c72b51b717
3 changed files with 204 additions and 273 deletions
242
access.lua
242
access.lua
|
@ -29,6 +29,7 @@ local logger = require("log")
|
|||
-- Just a note for the client to know that he passed through the SSO
|
||||
ngx.header["X-SSO-WAT"] = "You've just been SSOed"
|
||||
|
||||
local is_logged_in = hlp.refresh_logged_in()
|
||||
|
||||
--
|
||||
-- 1. LOGIN
|
||||
|
@ -66,7 +67,7 @@ end
|
|||
-- If the URL matches the portal URL, serve a portal file or proceed to a
|
||||
-- portal operation
|
||||
--
|
||||
if (ngx.var.host == conf["portal_domain"] or hlp.is_logged_in())
|
||||
if (ngx.var.host == conf["portal_domain"] or is_logged_in)
|
||||
and hlp.string.starts(ngx.var.uri, string.sub(conf["portal_path"], 1, -2))
|
||||
then
|
||||
|
||||
|
@ -94,7 +95,7 @@ then
|
|||
|
||||
-- If the `r` URI argument is set, it means that we want to
|
||||
-- be redirected (typically after a login phase)
|
||||
elseif hlp.is_logged_in() and uri_args.r then
|
||||
elseif is_logged_in and uri_args.r then
|
||||
-- Decode back url
|
||||
back_url = ngx.decode_base64(uri_args.r)
|
||||
|
||||
|
@ -145,7 +146,7 @@ then
|
|||
|
||||
-- In case we want to serve portal login or assets for portal, just
|
||||
-- serve it
|
||||
elseif hlp.is_logged_in()
|
||||
elseif is_logged_in
|
||||
or ngx.var.uri == conf["portal_path"]
|
||||
or (hlp.string.starts(ngx.var.uri, conf["portal_path"].."assets")
|
||||
and (not ngx.var.http_referer
|
||||
|
@ -197,13 +198,41 @@ then
|
|||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- 2 ... continued : portal assets that are available on every domains
|
||||
--
|
||||
-- For example: `https://whatever.org/ynhpanel.js` will serve the
|
||||
-- `/yunohost/sso/assets/js/ynhpanel.js` file.
|
||||
--
|
||||
|
||||
if is_logged_in then
|
||||
assets = {
|
||||
["/ynh_portal.js"] = "js/ynh_portal.js",
|
||||
["/ynh_overlay.css"] = "css/ynh_overlay.css"
|
||||
}
|
||||
theme_dir = "/usr/share/ssowat/portal/assets/themes/"..conf.theme
|
||||
local pfile = io.popen('find "'..theme_dir..'" -type f -exec realpath --relative-to "'..theme_dir..'" {} \\;')
|
||||
for filename in pfile:lines() do
|
||||
assets["/ynhtheme/"..filename] = "themes/"..conf.theme.."/"..filename
|
||||
end
|
||||
pfile:close()
|
||||
|
||||
for shortcut, full in pairs(assets) do
|
||||
if string.match(ngx.var.uri, "^"..shortcut.."$") then
|
||||
logger.debug("Serving static asset "..full)
|
||||
return hlp.serve("/yunohost/sso/assets/"..full, "static_asset")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- 3. Redirected URLs
|
||||
-- 3. REDIRECTED URLS
|
||||
--
|
||||
-- If the URL matches one of the `redirected_urls` in the configuration file,
|
||||
-- just redirect to the target URL/URI
|
||||
--
|
||||
|
||||
function detect_redirection(redirect_url)
|
||||
if hlp.string.starts(redirect_url, "http://")
|
||||
or hlp.string.starts(redirect_url, "https://") then
|
||||
|
@ -237,159 +266,84 @@ if conf["redirected_regex"] then
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
local longest_protected_match = hlp.longest_url_path(hlp.get_matches("protected")) or ""
|
||||
local longest_skipped_match = hlp.longest_url_path(hlp.get_matches("skipped")) or ""
|
||||
local longest_unprotected_match = hlp.longest_url_path(hlp.get_matches("unprotected")) or ""
|
||||
|
||||
logger.debug("Longest skipped : "..longest_skipped_match)
|
||||
logger.debug("Longest unprotected : "..longest_unprotected_match)
|
||||
logger.debug("Longest protected : "..longest_protected_match)
|
||||
|
||||
--
|
||||
-- 4. Skipped URLs
|
||||
-- 4. IDENTIFY THE RELEVANT PERMISSION
|
||||
--
|
||||
-- If the URL matches one of the `skipped_urls` in the configuration file,
|
||||
-- it means that the URL should not be protected by the SSO and no header
|
||||
-- has to be sent, even if the user is already authenticated.
|
||||
-- In particular, the conf is filled with permissions such as:
|
||||
--
|
||||
-- "foobar": {
|
||||
-- "auth_header": false,
|
||||
-- "label": "Foobar permission",
|
||||
-- "public": false,
|
||||
-- "show_tile": true,
|
||||
-- "uris": [
|
||||
-- "yolo.test/foobar",
|
||||
-- "re:^[^/]*/%.well%-known/foobar/.*$",
|
||||
-- ],
|
||||
-- "users": ["alice", "bob"]
|
||||
-- }
|
||||
--
|
||||
--
|
||||
-- And we find the best matching permission by trying to match the request uri
|
||||
-- against all the uris rules/regexes from the conf and keep the longest matching one.
|
||||
--
|
||||
|
||||
if longest_skipped_match ~= ""
|
||||
and string.len(longest_skipped_match) >= string.len(longest_protected_match)
|
||||
and string.len(longest_skipped_match) > string.len(longest_unprotected_match) then
|
||||
logger.debug("Skipping "..ngx.var.uri)
|
||||
return hlp.pass()
|
||||
end
|
||||
permission = nil
|
||||
longest_url_match = ""
|
||||
|
||||
--
|
||||
-- 5. Specific files (used in YunoHost)
|
||||
--
|
||||
-- We want to serve specific portal assets right at the root of the domain.
|
||||
--
|
||||
-- For example: `https://mydomain.org/ynhpanel.js` will serve the
|
||||
-- `/yunohost/sso/assets/js/ynhpanel.js` file.
|
||||
--
|
||||
for permission_name, permission_infos in pairs(conf["permissions"]) do
|
||||
if next(permission_infos['uris']) ~= nil then
|
||||
for _, url in pairs(permission_infos['uris']) do
|
||||
if string.starts(url, "re:") then
|
||||
url = string.sub(url, 4, string.len(url))
|
||||
end
|
||||
|
||||
function scandir(directory, callback)
|
||||
-- use find (and not ls) to list only files recursively and with their full path relative to the asked directory
|
||||
local pfile = io.popen('find "'..directory..'" -type f -exec realpath --relative-to "'..directory..'" {} \\;')
|
||||
for filename in pfile:lines() do
|
||||
callback(filename)
|
||||
end
|
||||
pfile:close()
|
||||
end
|
||||
|
||||
function serveAsset(shortcut, full)
|
||||
if string.match(ngx.var.uri, "^"..shortcut.."$") then
|
||||
logger.debug("Serving static asset "..full)
|
||||
hlp.serve("/yunohost/sso/assets/"..full, "static_asset")
|
||||
end
|
||||
end
|
||||
|
||||
function serveThemeFile(filename)
|
||||
serveAsset("/ynhtheme/"..filename, "themes/"..conf.theme.."/"..filename)
|
||||
end
|
||||
|
||||
function serveYnhpanel()
|
||||
logger.debug("Serving ynhpanel")
|
||||
|
||||
-- serve ynhpanel files
|
||||
serveAsset("/ynh_portal.js", "js/ynh_portal.js")
|
||||
serveAsset("/ynh_overlay.css", "css/ynh_overlay.css")
|
||||
-- serve theme's files
|
||||
-- FIXME? I think it would be better here not to use an absolute path
|
||||
-- but I didn't succeed to figure out where is the current location of the script
|
||||
-- if you call it from "portal/assets/themes/" the ls fails
|
||||
scandir("/usr/share/ssowat/portal/assets/themes/"..conf.theme, serveThemeFile)
|
||||
end
|
||||
|
||||
--
|
||||
-- 6. Unprotected URLs
|
||||
--
|
||||
-- If the URL matches one of the `unprotected_urls` in the configuration file,
|
||||
-- it means that the URL should not be protected by the SSO *but* headers have
|
||||
-- to be sent if the user is already authenticated.
|
||||
--
|
||||
-- It means that you can let anyone access to an app, but if a user has already
|
||||
-- been authenticated on the portal, he can have his authentication headers
|
||||
-- passed to the app.
|
||||
--
|
||||
|
||||
if longest_unprotected_match ~= ""
|
||||
and string.len(longest_unprotected_match) > string.len(longest_protected_match) then
|
||||
if hlp.is_logged_in() then
|
||||
serveYnhpanel()
|
||||
if hlp.has_access() then
|
||||
hlp.set_headers()
|
||||
local m = hlp.match(ngx.var.host..ngx.var.uri..hlp.uri_args_string(), url)
|
||||
if m ~= nil and string.len(m) > string.len(longest_url_match) then
|
||||
longest_url_match = m
|
||||
permission = permission_infos
|
||||
permission["id"] = permission_name
|
||||
end
|
||||
end
|
||||
end
|
||||
logger.debug(ngx.var.uri.." is in unprotected_urls")
|
||||
return hlp.pass()
|
||||
end
|
||||
|
||||
if hlp.is_logged_in() then
|
||||
serveYnhpanel()
|
||||
--
|
||||
--
|
||||
-- 5. APPLY PERMISSION
|
||||
--
|
||||
--
|
||||
|
||||
-- If user has no access to this URL, redirect him to the portal
|
||||
if not hlp.has_access() then
|
||||
-- 1st case : client has access
|
||||
|
||||
if hlp.has_access(permission) then
|
||||
|
||||
if is_logged_in then
|
||||
-- If the user is logged in, we set some additional headers
|
||||
hlp.set_headers()
|
||||
|
||||
-- If Basic Authorization header are disabled for this permission,
|
||||
-- remove them from the response
|
||||
if not permission["auth_header"] then
|
||||
ngx.req.clear_header("Authorization")
|
||||
end
|
||||
end
|
||||
|
||||
return hlp.pass()
|
||||
|
||||
-- 2nd case : no access ... redirect to portal / login form
|
||||
else
|
||||
|
||||
if is_logged_in then
|
||||
return hlp.redirect(conf.portal_url)
|
||||
end
|
||||
|
||||
-- If the user is authenticated and has access to the URL, set the headers
|
||||
-- and let it be
|
||||
hlp.set_headers()
|
||||
return hlp.pass()
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- 7. Basic HTTP Authentication
|
||||
--
|
||||
-- If the `Authorization` header is set before reaching the SSO, we want to
|
||||
-- match user and password against the user database.
|
||||
--
|
||||
-- It allows you to bypass the cookie-based procedure with a per-request
|
||||
-- authentication. Very usefull when you are trying to reach a specific URL
|
||||
-- via cURL for example.
|
||||
--
|
||||
|
||||
local auth_header = ngx.req.get_headers()["Authorization"]
|
||||
|
||||
if auth_header then
|
||||
_, _, b64_cred = string.find(auth_header, "^Basic%s+(.+)$")
|
||||
_, _, user, password = string.find(ngx.decode_base64(b64_cred), "^(.+):(.+)$")
|
||||
user = hlp.authenticate(user, password)
|
||||
if user then
|
||||
logger.debug("User got authenticated through basic auth")
|
||||
|
||||
-- If user has no access to this URL, redirect him to the portal
|
||||
if not hlp.has_access(user) then
|
||||
return hlp.redirect(conf.portal_url)
|
||||
else
|
||||
-- Only display this if HTTPS. For HTTP, we can't know if the user really is
|
||||
-- logged in or not, because the cookie is available only in HTTP...
|
||||
if ngx.var.scheme == "https" then
|
||||
hlp.flash("info", hlp.t("please_login"))
|
||||
end
|
||||
|
||||
hlp.set_headers(user)
|
||||
return hlp.pass()
|
||||
local back_url = "https://" .. ngx.var.host .. ngx.var.uri .. hlp.uri_args_string()
|
||||
return hlp.redirect(conf.portal_url.."?r="..ngx.encode_base64(back_url))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- 8. Redirect to login
|
||||
--
|
||||
-- If no previous rule has matched, just redirect to the portal login.
|
||||
-- The default is to protect every URL by default.
|
||||
--
|
||||
|
||||
-- Only display this if HTTPS. For HTTP, we can't know if the user really is
|
||||
-- logged in or not, because the cookie is available only in HTTP...
|
||||
if ngx.var.scheme == "https" then
|
||||
hlp.flash("info", hlp.t("please_login"))
|
||||
end
|
||||
|
||||
-- Force the scheme to HTTPS. This is to avoid an issue with redirection loop
|
||||
-- when trying to access http://main.domain.tld/ (SSOwat finds that user aint
|
||||
-- logged in, therefore redirects to SSO, which redirects to the back_url, which
|
||||
-- redirect to SSO, ..)
|
||||
logger.debug("No rule found for "..ngx.var.uri..". By default, redirecting to portal")
|
||||
local back_url = "https://" .. ngx.var.host .. ngx.var.uri .. hlp.uri_args_string()
|
||||
return hlp.redirect(conf.portal_url.."?r="..ngx.encode_base64(back_url))
|
||||
|
|
|
@ -97,7 +97,8 @@ function get_config()
|
|||
allow_mail_authentication = true,
|
||||
default_language = "en",
|
||||
theme = "default",
|
||||
logging = "fatal" -- Only log fatal messages by default (so apriori nothing)
|
||||
logging = "fatal", -- Only log fatal messages by default (so apriori nothing)
|
||||
permissions = {}
|
||||
}
|
||||
|
||||
|
||||
|
@ -123,7 +124,7 @@ function get_config()
|
|||
|
||||
|
||||
-- Always skip the portal to avoid redirection looping.
|
||||
table.insert(conf["skipped_urls"], conf["portal_domain"]..conf["portal_path"])
|
||||
table.insert(conf["permissions"]["core_skipped"]["uris"], conf["portal_domain"]..conf["portal_path"])
|
||||
|
||||
update_language()
|
||||
|
||||
|
|
230
helpers.lua
230
helpers.lua
|
@ -17,6 +17,8 @@ local url_parser = require "socket.url"
|
|||
-- Import Perl regular expressions library
|
||||
local rex = require "rex_pcre"
|
||||
|
||||
local is_logged_in = false
|
||||
|
||||
function refresh_config()
|
||||
conf = config.get_config()
|
||||
end
|
||||
|
@ -224,11 +226,13 @@ end
|
|||
-- Check if the session cookies are set, and rehash server + client information
|
||||
-- to match the session hash.
|
||||
--
|
||||
function is_logged_in()
|
||||
function refresh_logged_in()
|
||||
local expireTime = ngx.var.cookie_SSOwAuthExpire
|
||||
local user = ngx.var.cookie_SSOwAuthUser
|
||||
local authHash = ngx.var.cookie_SSOwAuthHash
|
||||
|
||||
authUser = nil
|
||||
|
||||
if expireTime and expireTime ~= ""
|
||||
and authHash and authHash ~= ""
|
||||
and user and user ~= ""
|
||||
|
@ -240,20 +244,46 @@ function is_logged_in()
|
|||
if session_key and session_key ~= "" then
|
||||
-- Check cache
|
||||
if cache:get(user.."-password") then
|
||||
authUser = user
|
||||
local hash = hmac_sha512(srvkey,
|
||||
authUser..
|
||||
user..
|
||||
"|"..expireTime..
|
||||
"|"..session_key)
|
||||
if hash ~= authHash then
|
||||
is_logged_in = hash == authHash
|
||||
if not is_logged_in then
|
||||
logger.info("Hash "..authHash.." rejected for "..user.."@"..ngx.var.remote_addr)
|
||||
else
|
||||
authUser = user
|
||||
end
|
||||
return hash == authHash
|
||||
return is_logged_in
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- If client set the `Authorization` header before reaching the SSO,
|
||||
-- we want to match user and password against the user database.
|
||||
--
|
||||
-- It allows to bypass the cookie-based procedure with a per-request
|
||||
-- authentication. This is useful to authenticate on the SSO during
|
||||
-- curl requests for example.
|
||||
|
||||
local auth_header = ngx.req.get_headers()["Authorization"]
|
||||
|
||||
if auth_header then
|
||||
_, _, b64_cred = string.find(auth_header, "^Basic%s+(.+)$")
|
||||
_, _, user, password = string.find(ngx.decode_base64(b64_cred), "^(.+):(.+)$")
|
||||
user = authenticate(user, password)
|
||||
if user then
|
||||
logger.debug("User got authenticated through basic auth")
|
||||
authUser = user
|
||||
is_logged_in = true
|
||||
else
|
||||
is_logged_in = false
|
||||
end
|
||||
return is_logged_in
|
||||
end
|
||||
|
||||
is_logged_in = false
|
||||
return false
|
||||
end
|
||||
|
||||
|
@ -266,113 +296,48 @@ function log_access(user, uri)
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
-- Check whether a user is allowed to access a URL using the `permissions` directive
|
||||
-- of the configuration file
|
||||
function has_access(user)
|
||||
function has_access(permission, user)
|
||||
user = user or authUser
|
||||
|
||||
logger.debug("User "..user.." try to access "..ngx.var.uri)
|
||||
|
||||
-- Get the longest url permission
|
||||
longest_permission_match = longest_url_path(permission_matches()) or ""
|
||||
|
||||
logger.debug("Longest permission match : "..longest_permission_match)
|
||||
|
||||
-- If no permission matches, it means that there is no permission defined for this url.
|
||||
if longest_permission_match == "" then
|
||||
logger.debug("No access rules defined for user "..user..", assuming it cannot access.")
|
||||
if permission == nil then
|
||||
logger.debug("No permission matching request for "..ngx.var.uri)
|
||||
return false
|
||||
end
|
||||
|
||||
-- All user in this permission
|
||||
allowed_users = conf["permissions"][longest_permission_match]
|
||||
-- Public access
|
||||
if user == nil or permission["public"] then
|
||||
user = user or "A visitor"
|
||||
logger.debug(user.." tries to access "..ngx.var.uri.." (corresponding perm: "..permission["id"]..")")
|
||||
return permission["public"]
|
||||
end
|
||||
|
||||
-- The user has permission to access the content if he is in the list of this one
|
||||
if allowed_users then
|
||||
for _, u in pairs(allowed_users) do
|
||||
if u == user then
|
||||
logger.debug("User "..user.." can access "..ngx.var.uri)
|
||||
log_access(user, longest_permission_match)
|
||||
logger.debug("User "..user.." tries to access "..ngx.var.uri.." (corresponding perm: "..permission["id"]..")")
|
||||
|
||||
-- The user has permission to access the content if he is in the list of allowed users
|
||||
if element_is_in_table(user, permission["users"]) then
|
||||
logger.debug("User "..user.." can access "..ngx.var.host..ngx.var.uri..uri_args_string())
|
||||
log_access(user, ngx.var.host..ngx.var.uri..uri_args_string())
|
||||
return true
|
||||
else
|
||||
logger.debug("User "..user.." cannot access "..ngx.var.uri)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function element_is_in_table(element, table)
|
||||
if table then
|
||||
for _, el in pairs(table) do
|
||||
if el == element then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
logger.debug("User "..user.." cannot access "..ngx.var.uri)
|
||||
return false
|
||||
end
|
||||
|
||||
function permission_matches()
|
||||
if not conf["permissions"] then
|
||||
conf["permissions"] = {}
|
||||
end
|
||||
|
||||
local url_matches = {}
|
||||
|
||||
for url, permission in pairs(conf["permissions"]) do
|
||||
if string.starts(ngx.var.host..ngx.var.uri..uri_args_string(), url) then
|
||||
logger.debug("Url permission match current uri : "..url)
|
||||
|
||||
table.insert(url_matches, url)
|
||||
end
|
||||
end
|
||||
|
||||
return url_matches
|
||||
end
|
||||
|
||||
function get_matches(section)
|
||||
if not conf[section.."_urls"] then
|
||||
conf[section.."_urls"] = {}
|
||||
end
|
||||
if not conf[section.."_regex"] then
|
||||
conf[section.."_regex"] = {}
|
||||
end
|
||||
|
||||
local url_matches = {}
|
||||
|
||||
for _, url in ipairs(conf[section.."_urls"]) do
|
||||
if string.starts(ngx.var.host..ngx.var.uri..uri_args_string(), url)
|
||||
or string.starts(ngx.var.uri..uri_args_string(), url) then
|
||||
logger.debug(section.."_url match current uri : "..url)
|
||||
table.insert(url_matches, url)
|
||||
end
|
||||
end
|
||||
for _, regex in ipairs(conf[section.."_regex"]) do
|
||||
local m1 = match(ngx.var.host..ngx.var.uri..uri_args_string(), regex)
|
||||
local m2 = match(ngx.var.uri..uri_args_string(), regex)
|
||||
if m1 then
|
||||
logger.debug(section.."_regex match current uri : "..regex.." with "..m1)
|
||||
table.insert(url_matches, m1)
|
||||
end
|
||||
if m2 then
|
||||
logger.debug(section.."_regex match current uri : "..regex.." with "..m2)
|
||||
table.insert(url_matches, m2)
|
||||
end
|
||||
end
|
||||
|
||||
return url_matches
|
||||
end
|
||||
|
||||
function longest_url_path(urls)
|
||||
local longest = nil
|
||||
for _, url in ipairs(urls) do
|
||||
-- Turn the url into a path, e.g.:
|
||||
-- /foo/bar -> /foo/bar
|
||||
-- domain.tld/foo/bar -> /foo/bar
|
||||
-- https://domain.tld:1234/foo/bar -> /foo/bar
|
||||
current = url_parser.parse(url).path
|
||||
if not longest or string.len(longest) < string.len(current) then
|
||||
longest = current
|
||||
end
|
||||
end
|
||||
if longest and string.ends(longest, "/") then
|
||||
longest = string.sub(longest, 1, -2)
|
||||
end
|
||||
return longest
|
||||
end
|
||||
|
||||
|
||||
-- Authenticate a user against the LDAP database using a username or an email
|
||||
-- address.
|
||||
-- Reminder: conf["ldap_identifier"] is "uid" by default
|
||||
|
@ -549,13 +514,13 @@ end
|
|||
-- It is used to render the SSOwat portal *only*.
|
||||
function serve(uri, cache)
|
||||
|
||||
logger.debug("Serving portal uri "..uri.." (if the corresponding file exists)")
|
||||
logger.debug("Serving portal uri "..uri)
|
||||
|
||||
rel_path = string.gsub(uri, conf["portal_path"], "/")
|
||||
|
||||
-- Load login.html as index
|
||||
if rel_path == "/" then
|
||||
if is_logged_in() then
|
||||
if is_logged_in then
|
||||
rel_path = "/portal.html"
|
||||
else
|
||||
rel_path = "/login.html"
|
||||
|
@ -656,40 +621,49 @@ function get_data_for(view)
|
|||
-- Needed if the LDAP db is changed outside ssowat (from the cli for example).
|
||||
-- Not doing it for ynhpanel.json only for performance reasons,
|
||||
-- so the panel could show wrong first name, last name or main email address
|
||||
if view ~= "ynhpanel.json" then
|
||||
delete_user_info_cache(user)
|
||||
end
|
||||
-- TODO: What if we remove info during logout?
|
||||
--if view ~= "ynhpanel.json" then
|
||||
-- delete_user_info_cache(user)
|
||||
--end
|
||||
|
||||
-- Be sure cache is loaded
|
||||
set_headers(user)
|
||||
if user then
|
||||
set_headers(user)
|
||||
|
||||
local mails = get_mails(user)
|
||||
data = {
|
||||
connected = true,
|
||||
theme = conf.theme,
|
||||
portal_url = conf.portal_url,
|
||||
uid = user,
|
||||
cn = cache:get(user.."-cn"),
|
||||
sn = cache:get(user.."-sn"),
|
||||
givenName = cache:get(user.."-givenName"),
|
||||
mail = mails["mail"],
|
||||
mailalias = mails["mailalias"],
|
||||
maildrop = mails["maildrop"],
|
||||
app = {}
|
||||
}
|
||||
local mails = get_mails(user)
|
||||
data = {
|
||||
connected = true,
|
||||
theme = conf.theme,
|
||||
portal_url = conf.portal_url,
|
||||
uid = user,
|
||||
cn = cache:get(user.."-cn"),
|
||||
sn = cache:get(user.."-sn"),
|
||||
givenName = cache:get(user.."-givenName"),
|
||||
mail = mails["mail"],
|
||||
mailalias = mails["mailalias"],
|
||||
maildrop = mails["maildrop"],
|
||||
app = {}
|
||||
}
|
||||
|
||||
local sorted_apps = {}
|
||||
local sorted_apps = {}
|
||||
|
||||
-- Add user's accessible URLs using the ACLs.
|
||||
-- It is typically used to build the app list.
|
||||
for url, name in pairs(conf["users"][user]) do
|
||||
-- Add user's accessible URLs using the ACLs.
|
||||
-- It is typically used to build the app list.
|
||||
for permission_name, permission in pairs(conf["permissions"]) do
|
||||
-- We want to display a tile, and uris is not empty
|
||||
if permission['show_tile'] and next(permission['uris']) ~= nil and element_is_in_table(user, permission["users"]) then
|
||||
url = permission['uris'][1]
|
||||
name = permission['label']
|
||||
|
||||
if ngx.var.host == conf["local_portal_domain"] then
|
||||
url = string.gsub(url, conf["original_portal_domain"], conf["local_portal_domain"])
|
||||
if ngx.var.host == conf["local_portal_domain"] then
|
||||
url = string.gsub(url, conf["original_portal_domain"], conf["local_portal_domain"])
|
||||
end
|
||||
|
||||
table.insert(sorted_apps, name)
|
||||
table.sort(sorted_apps)
|
||||
table.insert(data["app"], index_of(sorted_apps, name), { url = url, name = name })
|
||||
end
|
||||
end
|
||||
table.insert(sorted_apps, name)
|
||||
table.sort(sorted_apps)
|
||||
table.insert(data["app"], index_of(sorted_apps, name), { url = url, name = name })
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -768,7 +742,7 @@ function edit_user()
|
|||
|
||||
-- Ensure that user is logged in and has passed information
|
||||
-- before continuing.
|
||||
if is_logged_in() and args
|
||||
if is_logged_in and args
|
||||
then
|
||||
|
||||
-- Set HTTP status to 201
|
||||
|
@ -1061,12 +1035,14 @@ function logout()
|
|||
local args = ngx.req.get_uri_args()
|
||||
|
||||
-- Delete user cookie if logged in (that should always be the case)
|
||||
if is_logged_in() then
|
||||
if is_logged_in then
|
||||
delete_cookie()
|
||||
cache:delete("session_"..authUser)
|
||||
cache:delete(authUser.."-"..conf["ldap_identifier"]) -- Ugly trick to reload cache
|
||||
cache:delete(authUser.."-password")
|
||||
delete_user_info_cache(authUser)
|
||||
flash("info", t("logged_out"))
|
||||
is_logged_in = false
|
||||
end
|
||||
|
||||
-- Redirect with the `r` URI argument if it exists or redirect to portal
|
||||
|
|
Loading…
Add table
Reference in a new issue