diff --git a/access.lua b/access.lua index 09ca7e0..5a598c3 100644 --- a/access.lua +++ b/access.lua @@ -239,6 +239,14 @@ if conf["redirected_regex"] then 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 -- @@ -247,66 +255,14 @@ end -- has to be sent, even if the user is already authenticated. -- -if conf["skipped_urls"] then - for _, url in ipairs(conf["skipped_urls"]) do - if (hlp.string.starts(ngx.var.host..ngx.var.uri..hlp.uri_args_string(), url) - or hlp.string.starts(ngx.var.uri..hlp.uri_args_string(), url)) - then - logger.debug("Skipping "..ngx.var.uri) - return hlp.pass() - end - end -end - -if conf["skipped_regex"] then - for _, regex in ipairs(conf["skipped_regex"]) do - if (hlp.match(ngx.var.host..ngx.var.uri..hlp.uri_args_string(), regex) - or hlp.match(ngx.var.uri..hlp.uri_args_string(), regex)) - then - logger.debug("Skipping "..ngx.var.uri) - return hlp.pass() - end - end +if longest_skipped_match ~= "" +and string.len(longest_skipped_match) >= string.len(longest_protected_match) then + logger.debug("Skipping "..ngx.var.uri) + return hlp.pass() end -- --- 5. Protected URLs --- --- If the URL matches one of the `protected_urls` in the configuration file, --- we have to protect it even if the URL is also set in the `unprotected_urls`. --- It could be useful if you want to unprotect every URL except a few --- particular ones. --- - -function is_protected() - if not conf["protected_urls"] then - conf["protected_urls"] = {} - end - if not conf["protected_regex"] then - conf["protected_regex"] = {} - end - - for _, url in ipairs(conf["protected_urls"]) do - if hlp.string.starts(ngx.var.host..ngx.var.uri..hlp.uri_args_string(), url) - or hlp.string.starts(ngx.var.uri..hlp.uri_args_string(), url) then - logger.debug(ngx.var.uri.." is in protected_urls") - return true - end - end - for _, regex in ipairs(conf["protected_regex"]) do - if hlp.match(ngx.var.host..ngx.var.uri..hlp.uri_args_string(), regex) - or hlp.match(ngx.var.uri..hlp.uri_args_string(), regex) then - logger.debug(ngx.var.uri.." is in protected_regex") - return true - end - end - - logger.debug(ngx.var.uri.." is not in protected_urls/regex") - return false -end - --- --- 6. Specific files (used in YunoHost) +-- 5. Specific files (used in YunoHost) -- -- We want to serve specific portal assets right at the root of the domain. -- @@ -348,7 +304,7 @@ function serveYnhpanel() end -- --- 7. Unprotected URLs +-- 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 @@ -359,39 +315,17 @@ end -- passed to the app. -- -if conf["unprotected_urls"] then - for _, url in ipairs(conf["unprotected_urls"]) do - if (hlp.string.starts(ngx.var.host..ngx.var.uri..hlp.uri_args_string(), url) - or hlp.string.starts(ngx.var.uri..hlp.uri_args_string(), url)) - and not is_protected() then - if hlp.is_logged_in() then - serveYnhpanel() +if longest_unprotected_match ~= "" +and string.len(longest_unprotected_match) > string.len(longest_protected_match) then + if hlp.is_logged_in() then + serveYnhpanel() - hlp.set_headers() - end - logger.debug(ngx.var.uri.." is in unprotected_urls") - return hlp.pass() - end + hlp.set_headers() end + logger.debug(ngx.var.uri.." is in unprotected_urls") + return hlp.pass() end -if conf["unprotected_regex"] then - for _, regex in ipairs(conf["unprotected_regex"]) do - if (hlp.match(ngx.var.host..ngx.var.uri..hlp.uri_args_string(), regex) - or hlp.match(ngx.var.uri..hlp.uri_args_string(), regex)) - and not is_protected() then - if hlp.is_logged_in() then - serveYnhpanel() - - hlp.set_headers() - end - logger.debug(ngx.var.uri.." is in unprotected_regex") - return hlp.pass() - end - end -end - - if hlp.is_logged_in() then serveYnhpanel() @@ -408,7 +342,7 @@ end -- --- 8. Basic HTTP Authentication +-- 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. @@ -444,7 +378,7 @@ end -- --- 9. Redirect to login +-- 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. diff --git a/helpers.lua b/helpers.lua index 5b2849e..221422a 100644 --- a/helpers.lua +++ b/helpers.lua @@ -317,6 +317,39 @@ function permission_matches() 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 @@ -329,6 +362,9 @@ function longest_url_path(urls) longest = current end end + if longest and string.ends(longest, "/") then + longest = string.sub(longest, 1, -2) + end return longest end