diff options
Diffstat (limited to 'plugins/mod_invites.lua')
-rw-r--r-- | plugins/mod_invites.lua | 203 |
1 files changed, 106 insertions, 97 deletions
diff --git a/plugins/mod_invites.lua b/plugins/mod_invites.lua index 88690f7e..5ee9430a 100644 --- a/plugins/mod_invites.lua +++ b/plugins/mod_invites.lua @@ -1,10 +1,12 @@ -local id = require "util.id"; -local it = require "util.iterators"; +local id = require "prosody.util.id"; +local it = require "prosody.util.iterators"; local url = require "socket.url"; -local jid_node = require "util.jid".node; -local jid_split = require "util.jid".split; +local jid_node = require "prosody.util.jid".node; +local jid_split = require "prosody.util.jid".split; +local argparse = require "prosody.util.argparse"; +local human_io = require "prosody.util.human.io"; -local default_ttl = module:get_option_number("invite_expiry", 86400 * 7); +local default_ttl = module:get_option_period("invite_expiry", "1 week"); local token_storage; if prosody.process_type == "prosody" or prosody.shutdown then @@ -201,53 +203,103 @@ function use(token) --luacheck: ignore 131/use end --- shell command -do - -- Since the console is global this overwrites the command for - -- each host it's loaded on, but this should be fine. - - local get_module = require "core.modulemanager".get_module; - - local console_env = module:shared("/*/admin_shell/env"); - - -- luacheck: ignore 212/self - console_env.invite = {}; - function console_env.invite:create_account(user_jid) - local username, host = jid_split(user_jid); - local mod_invites, err = get_module(host, "invites"); - if not mod_invites then return nil, err or "mod_invites not loaded on this host"; end - local invite, err = mod_invites.create_account(username); +module:add_item("shell-command", { + section = "invite"; + section_desc = "Create and manage invitations"; + name = "create_account"; + desc = "Create an invitation to make an account on this server with the specified JID (supply only a hostname to allow any username)"; + args = { { name = "user_jid", type = "string" } }; + host_selector = "user_jid"; + + handler = function (self, user_jid) --luacheck: ignore 212/self + local username = jid_split(user_jid); + local invite, err = create_account(username); if not invite then return nil, err; end return true, invite.landing_page or invite.uri; - end - - function console_env.invite:create_contact(user_jid, allow_registration) - local username, host = jid_split(user_jid); - local mod_invites, err = get_module(host, "invites"); - if not mod_invites then return nil, err or "mod_invites not loaded on this host"; end - local invite, err = mod_invites.create_contact(username, allow_registration); + end; +}); + +module:add_item("shell-command", { + section = "invite"; + section_desc = "Create and manage invitations"; + name = "create_contact"; + desc = "Create an invitation to become contacts with the specified user"; + args = { { name = "user_jid", type = "string" }, { name = "allow_registration" } }; + host_selector = "user_jid"; + + handler = function (self, user_jid, allow_registration) --luacheck: ignore 212/self + local username = jid_split(user_jid); + local invite, err = create_contact(username, allow_registration); if not invite then return nil, err; end return true, invite.landing_page or invite.uri; - end -end + end; +}); + +local subcommands = {}; --- prosodyctl command function module.command(arg) - if #arg < 2 or arg[1] ~= "generate" then + local opts = argparse.parse(arg, { short_params = { h = "help"; ["?"] = "help" } }); + local cmd = table.remove(arg, 1); -- pop command + if opts.help or not cmd or not subcommands[cmd] then print("usage: prosodyctl mod_"..module.name.." generate example.com"); return 2; end - table.remove(arg, 1); -- pop command + return subcommands[cmd](arg); +end - local sm = require "core.storagemanager"; - local mm = require "core.modulemanager"; +function subcommands.generate(arg) + local function help(short) + print("usage: prosodyctl mod_" .. module.name .. " generate DOMAIN --reset USERNAME") + print("usage: prosodyctl mod_" .. module.name .. " generate DOMAIN [--admin] [--role ROLE] [--group GROUPID]...") + if short then return 2 end + print() + print("This command has two modes: password reset and new account.") + print("If --reset is given, the command operates in password reset mode and in new account mode otherwise.") + print() + print("required arguments in password reset mode:") + print() + print(" --reset USERNAME Generate a password reset link for the given USERNAME.") + print() + print("optional arguments in new account mode:") + print() + print(" --admin Make the new user privileged") + print(" Equivalent to --role prosody:admin") + print(" --role ROLE Grant the given ROLE to the new user") + print(" --group GROUPID Add the user to the group with the given ID") + print(" Can be specified multiple times") + print(" --expires-after T Time until the invite expires (e.g. '1 week')") + print() + print("--group can be specified multiple times; the user will be added to all groups.") + print() + print("--reset and the other options cannot be mixed.") + return 2 + end - local host = arg[1]; - assert(prosody.hosts[host], "Host "..tostring(host).." does not exist"); + local earlyopts = argparse.parse(arg, { short_params = { h = "help"; ["?"] = "help" } }); + if earlyopts.help or not earlyopts[1] then + return help(); + end + + local sm = require "prosody.core.storagemanager"; + local mm = require "prosody.core.modulemanager"; + + local host = table.remove(arg, 1); -- pop host + if not host then return help(true) end sm.initialize_host(host); - table.remove(arg, 1); -- pop host module.host = host; --luacheck: ignore 122/module token_storage = module:open_store("invite_token", "map"); + local opts = argparse.parse(arg, { + short_params = { h = "help"; ["?"] = "help"; g = "group" }; + value_params = { group = true; reset = true; role = true }; + array_params = { group = true; role = true }; + }); + + if opts.help then + return help(); + end + -- Load mod_invites local invites = module:depends("invites"); -- Optional community module that if used, needs to be loaded here @@ -257,71 +309,28 @@ function module.command(arg) end local allow_reset; - local roles; - local groups = {}; - - while #arg > 0 do - local value = arg[1]; - table.remove(arg, 1); - if value == "--help" then - print("usage: prosodyctl mod_"..module.name.." generate DOMAIN --reset USERNAME") - print("usage: prosodyctl mod_"..module.name.." generate DOMAIN [--admin] [--role ROLE] [--group GROUPID]...") - print() - print("This command has two modes: password reset and new account.") - print("If --reset is given, the command operates in password reset mode and in new account mode otherwise.") - print() - print("required arguments in password reset mode:") - print() - print(" --reset USERNAME Generate a password reset link for the given USERNAME.") - print() - print("optional arguments in new account mode:") - print() - print(" --admin Make the new user privileged") - print(" Equivalent to --role prosody:admin") - print(" --role ROLE Grant the given ROLE to the new user") - print(" --group GROUPID Add the user to the group with the given ID") - print(" Can be specified multiple times") - print() - print("--role and --admin override each other; the last one wins") - print("--group can be specified multiple times; the user will be added to all groups.") - print() - print("--reset and the other options cannot be mixed.") - return 2 - elseif value == "--reset" then - local nodeprep = require "util.encodings".stringprep.nodeprep; - local username = nodeprep(arg[1]) - table.remove(arg, 1); - if not username then - print("Please supply a valid username to generate a reset link for"); - return 2; - end - allow_reset = username; - elseif value == "--admin" then - roles = { ["prosody:admin"] = true }; - elseif value == "--role" then - local rolename = arg[1]; - if not rolename then - print("Please supply a role name"); - return 2; - end - roles = { [rolename] = true }; - table.remove(arg, 1); - elseif value == "--group" or value == "-g" then - local groupid = arg[1]; - if not groupid then - print("Please supply a group ID") - return 2; - end - table.insert(groups, groupid); - table.remove(arg, 1); - else - print("unexpected argument: "..value) + + if opts.reset then + local nodeprep = require "prosody.util.encodings".stringprep.nodeprep; + local username = nodeprep(opts.reset) + if not username then + print("Please supply a valid username to generate a reset link for"); + return 2; end + allow_reset = username; + end + + local roles = opts.role or {}; + local groups = opts.groups or {}; + + if opts.admin then + -- Insert it first since we don't get order out of argparse + table.insert(roles, 1, "prosody:admin"); end local invite; if allow_reset then - if roles then + if roles[1] then print("--role/--admin and --reset are mutually exclusive") return 2; end @@ -333,7 +342,7 @@ function module.command(arg) invite = assert(invites.create_account(nil, { roles = roles, groups = groups - })); + }, opts.expires_after and human_io.parse_duration(opts.expires_after))); end print(invite.landing_page or invite.uri); |