Mercurial > prosody-modules
view mod_invites_page/mod_invites_page.lua @ 5173:460f78654864
mod_muc_rtbl: also filter messages
This was a bit tricky because we don't want to run the JIDs
through SHA256 on each message. Took a while to come up with this
simple plan of just caching the SHA256 of the JIDs on the
occupants.
This will leave some dirt in the occupants after unloading the
module, but that should be ok; once they cycle the room, the
hashes will be gone.
This is direly needed, otherwise, there is a tight race between
the moderation activities and the actors joining the room.
author | Jonas Schäfer <jonas@wielicki.name> |
---|---|
date | Tue, 21 Feb 2023 21:37:27 +0100 |
parents | 75b6e5df65f9 |
children | efdaffc878a9 |
line wrap: on
line source
local st = require "util.stanza"; local url_escape = require "util.http".urlencode; local base_url = "https://"..module.host.."/"; local render_html_template = require"util.interpolation".new("%b{}", st.xml_escape, { urlescape = url_escape; lower = string.lower; classname = function (s) return (s:gsub("%W+", "-")); end; relurl = function (s) if s:match("^%w+://") then return s; end return base_url.."/"..s; end; }); local render_url = require "util.interpolation".new("%b{}", url_escape, { urlescape = url_escape; noscheme = function (url) return (url:gsub("^[^:]+:", "")); end; }); local site_name = module:get_option_string("site_name", module.host); local site_apps; -- Enable/disable built-in invite pages local external_only = module:get_option_boolean("invites_page_external", false); local http_files; if not external_only then -- Load HTTP-serving dependencies if prosody.shutdown then -- not if running under prosodyctl module:depends("http"); if prosody.process_type == "prosody" then http_files = require "net.http.files"; else http_files = module:depends"http_files"; end end -- Calculate automatic base_url default base_url = module.http_url and module:http_url(); -- Load site apps info module:depends("register_apps"); site_apps = module:shared("register_apps/apps"); end local invites = module:depends("invites"); -- Point at eg https://github.com/ge0rg/easy-xmpp-invitation -- This URL must always be absolute, as it is shared standalone local invite_url_template = module:get_option_string("invites_page", base_url and (base_url.."?{invite.token}") or nil); -- This URL is relative to the invite page, or can be absolute local register_url_template = module:get_option_string("invites_registration_page", "register?t={invite.token}&c={app.id}"); local function add_landing_url(invite) if not invite_url_template then return; end -- TODO: we don't currently have a landing page for subscription-only invites, -- so the user will only receive a URI. The client should be able to handle this -- by automatically falling back to a client-specific landing page, per XEP-0401. if not invite.allow_registration then return; end invite.landing_page = render_url(invite_url_template, { host = module.host, invite = invite }); end module:hook("invite-created", add_landing_url); if external_only then return; end local function render_app_urls(apps, invite_vars) local rendered_apps = {}; for _, unrendered_app in ipairs(apps) do local app = setmetatable({}, { __index = unrendered_app }); local template_vars = { app = app, invite = invite_vars, base_url = base_url }; if app.magic_link_format then -- Magic link generally links directly to third-party app.proceed_url = render_url(app.magic_link_format or app.link or "#", template_vars); elseif app.supports_preauth_uri then -- Proceed to a page that guides the user to download, and then -- click the URI button app.proceed_url = render_url("{base_url!}/setup/{app.id}?{invite.token}", template_vars); else -- Manual means proceed to web registration, but include app id -- so it can show post-registration instructions app.proceed_url = render_url(register_url_template, template_vars); end table.insert(rendered_apps, app); end return rendered_apps; end function serve_invite_page(event) local invite_page_template = assert(module:load_resource("html/invite.html")):read("*a"); local invalid_invite_page_template = assert(module:load_resource("html/invite_invalid.html")):read("*a"); event.response.headers["Content-Type"] = "text/html; charset=utf-8"; local invite = invites.get(event.request.url.query); if not invite then return render_html_template(invalid_invite_page_template, { site_name = site_name; static = base_url.."/static"; }); end local template_vars = { site_name = site_name; token = invite.token; uri = invite.uri; type = invite.type; jid = invite.jid; inviter = invite.inviter; static = base_url.."/static"; }; template_vars.apps = render_app_urls(site_apps, template_vars); local invite_page = render_html_template(invite_page_template, template_vars); event.response.headers["Link"] = ([[<%s>; rel="alternate"]]):format(template_vars.uri); return invite_page; end function serve_setup_page(event, app_id) local invite_page_template = assert(module:load_resource("html/client.html")):read("*a"); local invalid_invite_page_template = assert(module:load_resource("html/invite_invalid.html")):read("*a"); event.response.headers["Content-Type"] = "text/html; charset=utf-8"; local invite = invites.get(event.request.url.query); if not invite then return render_html_template(invalid_invite_page_template, { site_name = site_name; static = base_url.."/static"; }); end local template_vars = { site_name = site_name; apps = site_apps; token = invite.token; uri = invite.uri; type = invite.type; jid = invite.jid; static = base_url.."/static"; }; template_vars.app = render_app_urls({ site_apps[app_id] }, template_vars)[1]; local invite_page = render_html_template(invite_page_template, template_vars); return invite_page; end local mime_map = { png = "image/png"; svg = "image/svg+xml"; js = "application/javascript"; }; module:provides("http", { route = { ["GET"] = serve_invite_page; ["GET /setup/*"] = serve_setup_page; ["GET /static/*"] = http_files and http_files.serve({ path = module:get_directory().."/static", mime_map = mime_map }); }; });