# HG changeset patch # User bsw # Date 1613303199 -3600 # Node ID 3fb752f4afcb071ad6e1eb462ae80abf1a422f77 # Parent 036703d1b400cde6eb7e42f9abd05c8b41ffa6fa Cleanup of configuration files diff -r 036703d1b400 -r 3fb752f4afcb app/main/_prefork/10_init.lua --- a/app/main/_prefork/10_init.lua Fri Feb 12 17:59:21 2021 +0100 +++ b/app/main/_prefork/10_init.lua Sun Feb 14 12:46:39 2021 +0100 @@ -126,6 +126,10 @@ if not config.oauth2.dynamic_registration_lifetime then config.oauth2.dynamic_registration_lifetime = 60 * 60 * 24 end + if config.oauth2.refresh_pause < config.oauth2.refresh_grace_period then + print("ERROR: config.auth2.refresh_pause is smaller than config.oauth2.refresh_grace_period") + os.exit() + end end if not config.database then diff -r 036703d1b400 -r 3fb752f4afcb config/_ldap.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/config/_ldap.lua Sun Feb 14 12:46:39 2021 +0100 @@ -0,0 +1,59 @@ +config.ldap = { + hosts = { + { + { uri = "ldap://192.168.1.1", tls = true, timeout = 5 }, + { uri = "ldap://192.168.1.2", tls = true, timeout = 5 }, + }, + { uri = "ldap://192.168.1.3", tls = true, timeout = 5 }, + }, + base = "dc=example,dc=org", + bind_as = { dn = "cn=admin,dc=example,dc=org", password = "secure" }, + member = { + registration = "auto", + scope = "subtree", + login_normalizer = function (login) + return login:lower() + end, + login_filter_map = function (login) + return "(uid=" .. ldap.escape_filter(login) .. ")" + end, + login_map = function (ldap_entry) + return ldap_entry.uid[1] + end, + uid_filter_map = function (uid) + return "(uidNumber=" .. ldap.escape_filter(uid) .. ")" + end, + uid_map = function (ldap_entry) + return ldap_entry.uidNumber[1] + end, + fetch_attr = { "uid", "uidNumber", "givenName", "sn", "displayName", "memberof" }, + attr_map = function (ldap_entry, member) + member.identification = ldap_entry.givenName[1] .. " " .. ldap_entry.sn[1] + member.name = ldap_entry.displayName[1] + end, + privilege_map = function (ldap_entry, member) + local privileges + if ldap_entry.dn:match("ou=people,dc=example,dc=org") then + privileges = { + { unit_id = 1, voting_right = true, polling_right = true }, + { unit_id = 2, voting_right = true, polling_right = false }, + { unit_id = 3, voting_right = false, polling_right = true } + } + elseif ldap_entry.dn:match("ou=employees,dc=example,dc=org$") then + privileges = { + { unit_id = 1, voting_right = false, polling_right = true }, + { unit_id = 2, voting_right = false, polling_right = true }, + { unit_id = 3, voting_right = true, polling_right = false } + } + elseif ldap_entry.dn:match("ou=member,dc=example,dc=org$") then + privileges = { + { unit_id = 1, voting_right = true, polling_right = false } + } + end + return privileges + end, + cache_passwords = true, + locked_profile_fields = { name = true } + } +} + diff -r 036703d1b400 -r 3fb752f4afcb config/_ldap_ad.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/config/_ldap_ad.lua Sun Feb 14 12:46:39 2021 +0100 @@ -0,0 +1,66 @@ +local function str2hex(s) + local t = {string.byte(s, 1, #s)} + local f = string.format + for i = 1, #t do t[i] = f("\\%02x", t[i]) end + return table.concat(t) +end + +config.ldap = { + hosts = { + { uri = "ldap://192.168.1.1", tls = true, timeout = 5 }, + { uri = "ldap://192.168.1.2", tls = true, timeout = 5 } + }, + base = "CN=Users,DC=example,DC=org", + bind_as = { dn = "CN=LiquidFeedback Service,CN=Users,DC=example,DC=org", password = "secure" }, + member = { + registration = "auto", + scope = "subtree", + login_normalizer = function (login) + return login:lower() + end, + login_filter_map = function (login) + return "(sAMAccountName=" .. ldap.escape_filter(login) .. ")" + end, + login_map = function (ldap_entry) + return ldap_entry.sAMAccountName[1] + end, + uid_filter_map = function (uid) + return "(objectGUID=" .. uid .. ")" + end, + uid_map = function (ldap_entry) + return str2hex(ldap_entry.objectGUID[1]) + end, + allowed_map = function (ldap_entry) + local allowed = false + if ldap_entry.memberOf then + for i, group in ipairs(ldap_entry.memberOf) do + if group == "CN=LiquidFeedback User,CN=Users,DC=example,DC=org" then + allowed = true + end + end + end + return allowed + end, + fetch_attr = { "sAMAccountName", "objectGUID", "givenName", "name", "displayName", "memberOf" }, + attr_map = function (ldap_entry, member) + member.identification = ldap_entry.givenName[1] .. " " .. ldap_entry.name[1] + member.name = ldap_entry.displayName[1] + end, + privilege_map = function (ldap_entry, member) + local privileges = {} + if ldap_entry.memberOf then + for i, group in ipairs(ldap_entry.memberOf) do + if group == "CN=LiquidFeedback User,CN=Users,DC=example,DC=org" then + table.insert(privileges, + { unit_id = 1, voting_right = true, polling_right = true } + ) + end + end + end + return privileges + end, + cache_passwords = true, + locked_profile_fields = { name = true } + } +} + diff -r 036703d1b400 -r 3fb752f4afcb config/_lf4rcs.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/config/_lf4rcs.lua Sun Feb 14 12:46:39 2021 +0100 @@ -0,0 +1,115 @@ +-- Configuration of lf4rcs +-- ------------------------------------------------------------------------ +config.lf4rcs = {} + +-- Example configuration for controlling a Git repository + +config.lf4rcs.git = { + + render_draft_reference = function(url, draft) + if not draft.external_reference then return end + ui.tag{ content = _"Changeset:" } + slot.put(" ") + ui.link{ + text = draft.external_reference, + external = url .. ";a=commit;h=" .. draft.external_reference + } + end, + + get_remote_user = function() + return os.getenv("REMOTE_USER") + end, + + get_branches = function(path, exec) + local branches = {} + for line in io.lines() do + local oldrev, newrev, branch = string.match(line, "([^ ]+) ([^ ]+) refs/heads/(.+)") + if not branch then + return nil, "unexpected format from git hook environment" + end + branches[branch] = { newrev } + end + return branches + end, + + commit = function(path, exec, branch, target_node_id, close_message, merge_message) + if merge_message then + exec("git", "-C", path, "checkout", "-f", "master") + exec("git", "-C", path, "merge", target_node_id, "-m", merge_message) + exec("git", "-C", path, "push", "origin", "master") + end + end + +} + +-- Example configuration for controlling a Mercurial repository +config.lf4rcs.hg = { + + working_branch_name = "work", + + render_draft_reference = function(url, draft) + if not draft.external_reference then return end + ui.tag{ content = _"Changeset graph:" } + slot.put(" ") + ui.link{ + text = draft.external_reference, + external = url .. "/graph/" .. draft.external_reference + } + end, + + get_remote_user = function() + return os.getenv("REMOTE_USER") + end, + + get_branches = function(path, exec) + local first_node_id = os.getenv("HG_NODE") + if not first_node_id then + return nil, "internal error, no first node ID available" + end + local hg_log = exec( + "hg", "log", "-R", path, "-r", first_node_id .. ":", "--template", "{branches}\n" + ) + local branches = {} + for branch in hg_log:gmatch("(.-)\n") do + if branch == "" then branch = "default" end + if not branches[branch] then + branches[branch] = {} + local head_lines = exec( + "hg", "heads", "-R", path, "--template", "{node}\n", branch + ) + for node_id in string.gmatch(head_lines, "[^\n]+") do + table.insert(branches[branch], node_id) + end + end + end + return branches + end, + + extra_checks = function(path, exec) + local result = exec("hg", "heads", "-t", "-c") + for branch in string.gmatch(result, "[^\n]+") do + if branch == lf4rcs.config.hg.working_branch_name then + return nil, "open head found for branch " .. lf4rcs.config.hg.working_branch_name + end + end + return true + end, + + commit = function(path, exec, branch, target_node_id, close_message, merge_message) + exec("hg", "up", "-R", path, "-C", "-r", target_node_id) + exec("hg", "commit", "-R", path, "--close-branch", "-m", close_message) + if merge_message then + exec("hg", "up", "-R", path, "-C", "-r", "default") + exec("hg", "merge", "-R", path, "-r", "tip") + exec("hg", "commit", "-R", path, "-m", merge_message) + end + end + +} + +-- Grace period after creating an initiative for pushing changes during verification phase +-- disabled by default (nil), use PostgreSQL interval notation +-- config.lf4rcs.push_grace_period = nil + +lf4rcs.init() + diff -r 036703d1b400 -r 3fb752f4afcb config/example.lua --- a/config/example.lua Fri Feb 12 17:59:21 2021 +0100 +++ b/config/example.lua Sun Feb 14 12:46:39 2021 +0100 @@ -4,40 +4,7 @@ -- Name of this instance, defaults to name of config file -- ------------------------------------------------------------------------ -config.instance_name = "Instance name" - - --- Information about service provider (HTML) --- ------------------------------------------------------------------------ -config.app_service_provider = "Snake Oil
10000 Berlin
Germany" - - --- A HTML formatted text the user has to accept while registering --- ------------------------------------------------------------------------ -config.use_terms = "

Terms of Use

Insert terms here

" - - --- Checkbox(es) the user has to accept while registering --- ------------------------------------------------------------------------ ---[[ -config.use_terms_checkboxes = { - { - name = "terms_of_use_v1", - html = "I accept the terms of use.", - not_accepted_error = "You have to accept the terms of use to be able to register." - }, - { - name = "extra_terms_of_use_v1", - html = "I accept the extra terms of use.", - not_accepted_error = "You have to accept the extra terms of use to be able to register." - } -} ---]] - --- Absolute base url of application --- ------------------------------------------------------------------------ -config.absolute_base_url = "http://example.com/" -config.localhost = false +config.instance_name = "Example Organisation" -- Connection information for the LiquidFeedback database @@ -45,31 +12,32 @@ config.database = { engine='postgresql', dbname='liquid_feedback' } --- Location of the rocketwiki binaries +-- Absolute base url of application +-- ------------------------------------------------------------------------ +config.absolute_base_url = "https://example.org/" + + +-- Network interface to bind to +-- ------------------------------------------------------------------------ +-- Available options: +-- true: bind to localhost (default) +-- false: bind to all interface -- ------------------------------------------------------------------------ -config.enforce_formatting_engine = "markdown2" -config.formatting_engines = { - { id = "markdown2", - name = "python-markdown2", - executable = "markdown2", - args = {'-s', 'escape', '-x', 'nofollow,wiki-tables'}, - remove_images = true - }, --- { id = "markdown_py", --- name = "Python Markdown", --- executable = "markdown_py", --- args = {'-s', 'escape', '-x', 'extra', '-x', 'nl2br', '-x', 'sane_lists'}, --- remove_images = true --- }, --- { id = "rocketwiki", --- name = "RocketWiki", --- executable = "/opt/rocketwiki-lqfb/rocketwiki-lqfb" --- }, --- { id = "compat", --- name = "Traditional WIKI syntax", --- executable = "/opt/rocketwiki-lqfb/rocketwiki-lqfb-compat" --- }, -} +-- config.localhost = true + + +-- Network port to bind to, default port 8080 +-- ------------------------------------------------------------------------ +-- config.port = 8080 + + +-- Serving content via IPV6 +-- ------------------------------------------------------------------------ +-- Available options: +-- nil or false: do not serve via IPv6 (default) +-- true: serve via IPv6 +-- ------------------------------------------------------------------------ +-- config.ipv6 = false -- Public access level @@ -88,7 +56,12 @@ -- "everything" -- -> Show everything a member can see, including profile pages -- ------------------------------------------------------------------------ -config.public_access = "authors_pseudonymous" +config.public_access = "none" + + +-- Information about service provider (HTML) +-- ------------------------------------------------------------------------ +config.app_service_provider = "Snake Oil
10000 Berlin
Germany" @@ -97,15 +70,6 @@ -- Remove leading -- to use a option -- ======================================================================== --- Disable registration --- ------------------------------------------------------------------------ --- Available options: --- false: registration is enabled (default) --- true: registration is disabled --- ------------------------------------------------------------------------ --- config.disable_registration = true - - -- List of enabled languages, defaults to available languages -- ------------------------------------------------------------------------ -- config.enabled_languages = { 'en', 'de', 'eo', 'el', 'hu', 'it', 'ka', 'nl', 'zh-Hans', 'zh-TW' } @@ -116,6 +80,35 @@ -- config.default_lang = "en" +-- Disable registration +-- ------------------------------------------------------------------------ +-- Available options: +-- false: registration is enabled (default) +-- true: registration is disabled +-- ------------------------------------------------------------------------ +-- config.disable_registration = true + + +-- A HTML formatted text the user has to accept while registering +-- ------------------------------------------------------------------------ +-- config.use_terms = "

Terms of Use

Insert terms here

" + + +-- Checkbox(es) the user has to accept while registering +-- ------------------------------------------------------------------------ +-- config.use_terms_checkboxes = { +-- { +-- name = "terms_of_use_v1", +-- html = "I accept the terms of use.", +-- not_accepted_error = "You have to accept the terms of use to be able to register." +-- }, +-- { +-- name = "extra_terms_of_use_v1", +-- html = "I accept the extra terms of use.", +-- not_accepted_error = "You have to accept the extra terms of use to be able to register." +-- } +-- } + -- after how long is a user considered inactive and the trustee will see warning, -- notation is according to postgresql intervals, default: no warning at all -- ------------------------------------------------------------------------ @@ -125,8 +118,8 @@ -- after which time a user is advised (_soft) or forced (_hard) to check -- unit and area delegations. default: no check at all -- ------------------------------------------------------------------------ +-- config.check_delegations_interval_soft = "3 months" -- config.check_delegations_interval_hard = "6 months" --- config.check_delegations_interval_soft = "3 months" -- default option when checking delegations @@ -174,11 +167,6 @@ -- config.password_hash_max_rounds = 20000 --- Supply custom url for avatar/photo delivery --- ------------------------------------------------------------------------ --- config.fastpath_url_func = nil - - -- Local directory for database dumps offered for download -- ------------------------------------------------------------------------ -- config.download_dir = nil @@ -197,6 +185,32 @@ -- photo = function(data) return extos.pfilter(data, "convert", "jpeg:-", "-thumbnail", "240x240", "jpeg:-") end --} +-- Initiative attachments +-- ------------------------------------------------------------------------ +-- config.attachments = {} + +-- Conversion function for recoding attachments +-- ------------------------------------------------------------------------ +-- config.attachments.convert_func = function(data) +-- return extos.pfilter(data, "convert", "jpeg:-", "-thumbnail", "240x240", "jpeg:-") +-- end + +-- Custom UI colors, defaults to green/blue +-- ------------------------------------------------------------------------ +-- config.style = { +-- color_md = { +-- primary = "green", +-- primary_contrast = "dark", +-- accent = "blue", +-- accent_contrast = "dark" +-- } +-- } + +-- Member profile fields, defaults to no extra fields +-- ------------------------------------------------------------------------ +-- config.member_profile_fields = {} + + -- Display a html formatted public message of the day -- ------------------------------------------------------------------------ @@ -208,16 +222,6 @@ -- config.motd_intern = "

Message of the day (intern)

The MOTD is formatted with HTML

" --- Integration of Etherpad, disabled by default --- ------------------------------------------------------------------------ ---config.etherpad = { --- base_url = "http://example.com:9001/", --- api_base = "http://localhost:9001/", --- api_key = "mysecretapikey", --- group_id = "mygroupname", --- cookie_path = "/" ---} - -- Free timings -- ------------------------------------------------------------------------ @@ -264,121 +268,6 @@ } --]] --- Configuration of lf4rcs --- ------------------------------------------------------------------------ --- config.lf4rc = {} - --- Example configuration for controlling a Git repository ---[[ -config.lf4rcs.git = { - - render_draft_reference = function(url, draft) - if not draft.external_reference then return end - ui.tag{ content = _"Changeset:" } - slot.put(" ") - ui.link{ - text = draft.external_reference, - external = url .. ";a=commit;h=" .. draft.external_reference - } - end, - - get_remote_user = function() - return os.getenv("REMOTE_USER") - end, - - get_branches = function(path, exec) - local branches = {} - for line in io.lines() do - local oldrev, newrev, branch = string.match(line, "([^ ]+) ([^ ]+) refs/heads/(.+)") - if not branch then - return nil, "unexpected format from git hook environment" - end - branches[branch] = { newrev } - end - return branches - end, - - commit = function(path, exec, branch, target_node_id, close_message, merge_message) - if merge_message then - exec("git", "-C", path, "checkout", "-f", "master") - exec("git", "-C", path, "merge", target_node_id, "-m", merge_message) - exec("git", "-C", path, "push", "origin", "master") - end - end - -} - --- Example configuration for controlling a Mercurial repository -config.lf4rcs.hg = { - - working_branch_name = "work", - - render_draft_reference = function(url, draft) - if not draft.external_reference then return end - ui.tag{ content = _"Changeset graph:" } - slot.put(" ") - ui.link{ - text = draft.external_reference, - external = url .. "/graph/" .. draft.external_reference - } - end, - - get_remote_user = function() - return os.getenv("REMOTE_USER") - end, - - get_branches = function(path, exec) - local first_node_id = os.getenv("HG_NODE") - if not first_node_id then - return nil, "internal error, no first node ID available" - end - local hg_log = exec( - "hg", "log", "-R", path, "-r", first_node_id .. ":", "--template", "{branches}\n" - ) - local branches = {} - for branch in hg_log:gmatch("(.-)\n") do - if branch == "" then branch = "default" end - if not branches[branch] then - branches[branch] = {} - local head_lines = exec( - "hg", "heads", "-R", path, "--template", "{node}\n", branch - ) - for node_id in string.gmatch(head_lines, "[^\n]+") do - table.insert(branches[branch], node_id) - end - end - end - return branches - end, - - extra_checks = function(path, exec) - local result = exec("hg", "heads", "-t", "-c") - for branch in string.gmatch(result, "[^\n]+") do - if branch == lf4rcs.config.hg.working_branch_name then - return nil, "open head found for branch " .. lf4rcs.config.hg.working_branch_name - end - end - return true - end, - - commit = function(path, exec, branch, target_node_id, close_message, merge_message) - exec("hg", "up", "-R", path, "-C", "-r", target_node_id) - exec("hg", "commit", "-R", path, "--close-branch", "-m", close_message) - if merge_message then - exec("hg", "up", "-R", path, "-C", "-r", "default") - exec("hg", "merge", "-R", path, "-r", "tip") - exec("hg", "commit", "-R", path, "-m", merge_message) - end - end - -} - --- Grace period after creating an initiative for pushing changes during verification phase --- disabled by default (nil), use PostgreSQL interval notation --- config.lf4rcs.push_grace_period = nil - -lf4rcs.init() ---]] -- External references -- ------------------------------------------------------------------------ @@ -399,45 +288,44 @@ end --]] + +-- Configuration of OAuth2 service, defaults to OAuth2 disabled +-- ------------------------------------------------------------------------ +-- config.oauth2 = {} + +-- Additional scopes +-- config.oauth2.available_scopes = { +-- { scope = "privA", name = { de = "Beispielprivileg A", en = "Example privilege A" } }, +-- { scope = "privB", name = { de = "Beispielprivileg B", en = "Example privilege B" } } +-- } + +-- OAuth2 endpoint magic string for dynamic app registration +-- ------------------------------------------------------------------------ +-- config.oauth2.endpoint_magic = "liquidfeedback_client_redirection_endpoint" + +-- OAuth2 Token lifetime and timings +-- ------------------------------------------------------------------------ +-- config.oauth2.authorization_code_lifetime = 5 * 60 +-- config.oauth2.refresh_token_lifetime = 60 * 60 * 24 * 30 * 3 +-- config.oauth2.refresh_pause = 60 +-- config.oauth2.refresh_grace_period = 60 +-- config.oauth2.access_token_lifetime = 60 * 60 + + + -- Admin logger -- ------------------------------------------------------------------------ -- Logging administrative activities -- disabled by default ---[[ -config.admin_logger = function(params) - - local adminid = app.session.member_id - local adminname = app.session.member.name - local url = params._webmcp_path - - -- do something (e.g. calling 'logger' via extos.pfilter) - -end ---]] +-- config.admin_logger = function(params) +-- local adminid = app.session.member_id +-- local adminname = app.session.member.name +-- local url = params._webmcp_path +-- -- do something (e.g. calling 'logger' via extos.pfilter) +-- end --- Network interface to bind to --- ------------------------------------------------------------------------ --- Available options: --- true: bind to localhost (default) --- false: bind to all interface --- ------------------------------------------------------------------------ --- config.localhost = true - - --- Network port to bind to --- ------------------------------------------------------------------------ --- config.port = 8080 - - --- Serving content via IPV6 --- ------------------------------------------------------------------------ --- Available options: --- nil or false: do not serve via IPv6 (default) --- true: serve via IPv6 --- ------------------------------------------------------------------------ --- config.ipv6 = false -- Application server fork configuration @@ -483,28 +371,42 @@ -- ------------------------------------------------------------------------ -- uncomment the following line to enable debug trace -- ------------------------------------------------------------------------ -config.enable_debug_trace = true +-- config.enable_debug_trace = true + + +-- Configuration of lf4rcs, disabled by default +-- for example configration see _lf4rcs.lua +-- ------------------------------------------------------------------------ +-- execute.config("_lf4rcs") + + +-- Configuration of ldap authentication, disabled by default +-- for example configration, see _ldap.lua +-- for active directory example, see _ldap_ad.lua +-- ------------------------------------------------------------------------ +-- execute.config("_ldap") +-- execute.config("_ldap_ad") -config.fork = { - pre =1, min = 1, max = 1, max_requests = 1, min_requests = 1 -} - -config.localhost = true +-- Integration of Etherpad, disabled by default +-- ------------------------------------------------------------------------ +--config.etherpad = { +-- base_url = "http://example.com:9001/", +-- api_base = "http://localhost:9001/", +-- api_key = "mysecretapikey", +-- group_id = "mygroupname", +-- cookie_path = "/" +--} -config.oauth2 = { - available_scopes = { - { scope = "read", name = { de = "Lesen", en = "Read data" } }, - { scope = "write", name = { de = "Schreiben", en = "Write data" } }, - { scope = "privA", name = { de = "Beispielprivileg A", en = "Example privilege A" } }, - { scope = "privB", name = { de = "Beispielprivileg B", en = "Example privilege B" } } - }, - authorization_code_lifetime = 5 * 60, - refresh_token_lifetime = 60 * 60 * 24 * 30 * 3, - refresh_pause = 60, - refresh_grace_period = 60, - access_token_lifetime = 60 * 60, - -- NOTE for init.lua : check for refresh_pause >= refresh_grace_period - endpoint_magic = "liquidfeedback_client_redirection_endpoint" +-- Integration of FirstLife +-- ------------------------------------------------------------------------ +--[[ +config.firstlife = { + coordinates = "", + areaviewer_url = "about:blank", + inputmap_url = "about:blank" } +config.allow_new_draft_callback = true +--]] +