diff --git a/ansible/files/prosody.cfg.lua b/ansible/files/prosody.cfg.lua index b55c6b9..83fed8f 100644 --- a/ansible/files/prosody.cfg.lua +++ b/ansible/files/prosody.cfg.lua @@ -75,6 +75,7 @@ modules_enabled = { "update_notify"; "turncredentials"; "admin_shell"; + "isolate_host"; "snikket_client_id"; "snikket_ios_preserve_push"; @@ -140,6 +141,9 @@ registration_invite_only = true -- over what happens when a user invites someone. allow_contact_invites = false +-- Disallow restricted users to create invitations to the server +deny_user_invites_by_roles = { "prosody:restricted" } + invites_page = ENV_SNIKKET_INVITE_URL or ("https://"..DOMAIN.."/invite/{invite.token}/"); invites_page_external = true @@ -203,6 +207,9 @@ if ENV_SNIKKET_TWEAK_TURNSERVER ~= "0" or ENV_SNIKKET_TWEAK_TURNSERVER_DOMAIN th turncredentials_secret = ENV_SNIKKET_TWEAK_TURNSERVER_SECRET or assert(io.open("/snikket/prosody/turn-auth-secret-v2")):read("*l"); end +-- Allow restricted users access to push notification servers +isolate_except_domains = { "push.snikket.net", "push-ios.snikket.net" } + VirtualHost (DOMAIN) authentication = "internal_hashed" @@ -234,11 +241,15 @@ Component ("groups."..DOMAIN) "muc" "vcard_muc"; "muc_defaults"; "muc_offline_delivery"; + "snikket_restricted_users"; } restrict_room_creation = "local" muc_local_only = { "general@groups."..DOMAIN } - muc_room_default_persistent = true + + -- Default configuration for rooms (typically overwritten by the client) muc_room_default_allow_member_invites = true + muc_room_default_persistent = true + muc_room_default_public = false default_mucs = { { diff --git a/ansible/snikket.yml b/ansible/snikket.yml index 2d20a87..d9c45cc 100644 --- a/ansible/snikket.yml +++ b/ansible/snikket.yml @@ -7,9 +7,9 @@ vars: prosody: package: "prosody-trunk" - build: "1521" + build: "1535" prosody_modules: - revision: "8b3e91249cff" + revision: "8bd36bba2292" tasks: - import_tasks: tasks/prosody.yml - import_tasks: tasks/supervisor.yml diff --git a/ansible/tasks/prosody.yml b/ansible/tasks/prosody.yml index 9921571..ee3c406 100644 --- a/ansible/tasks/prosody.yml +++ b/ansible/tasks/prosody.yml @@ -122,6 +122,7 @@ - mod_prometheus - mod_spam_reporting - mod_watch_spam_reports + - mod_isolate_host - name: Enable wanted modules (snikket-modules) file: @@ -135,6 +136,7 @@ - mod_invites_bootstrap - mod_snikket_client_id - mod_snikket_ios_preserve_push + - mod_snikket_restricted_users - name: "Install lua-ossl for encrypted push notifications" apt: diff --git a/snikket-modules/mod_snikket_restricted_users/mod_snikket_restricted_users.lua b/snikket-modules/mod_snikket_restricted_users/mod_snikket_restricted_users.lua new file mode 100644 index 0000000..a7d5f80 --- /dev/null +++ b/snikket-modules/mod_snikket_restricted_users/mod_snikket_restricted_users.lua @@ -0,0 +1,54 @@ +local jid_bare = require "util.jid".bare; +local um_get_roles = require "core.usermanager".get_roles; + +local function load_main_host(module) + -- Check whether a user should be isolated from remote JIDs + -- If not, set a session flag that allows them to bypass mod_isolate_host + local function check_user_isolated(event) + local session = event.session; + if not session.no_host_isolation then + local bare_jid = jid_bare(session.full_jid); + local roles = um_get_roles(bare_jid, module.host); + if roles and not roles["prosody:restricted"] then + -- Bypass isolation for all unrestricted users + session.no_host_isolation = true; + end + end + end + + -- Add low-priority hook to run after the check_user_isolated default + -- behaviour in mod_isolate_host + module:hook("resource-bind", check_user_isolated, -0.5); +end + +local function load_groups_host(module) + local primary_host = module.host:gsub("^%a+%.", ""); + + local function is_restricted(user_jid) + local roles = um_get_roles(user_jid, primary_host); + return not roles or roles["prosody:restricted"]; + end + + module:hook("muc-config-submitted/muc#roomconfig_publicroom", function (event) + if not is_restricted(event.actor) then return; end + -- Don't allow modification of this value by restricted users + return true; + end, 5); + + module:hook("muc-config-form", function (event) + if not is_restricted(event.actor) then return; end -- Don't restrict admins + -- Hide the option from the config form for restricted users + local form = event.form; + for i = #form, 1, -1 do + if form[i].name == "muc#roomconfig_publicroom" then + table.remove(form, i); + end + end + end); +end + +if module:get_host_type() == "component" and module:get_option_string("component_module") == "muc" then + load_groups_host(module); +else + load_main_host(module); +end