Software /
code /
prosody
Comparison
plugins/mod_invites.lua @ 13738:26a0f653793e 13.0
mod_invites: Deprecate 'mod_invites generate' in favour of new shell commands
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Mon, 17 Feb 2025 19:12:40 +0000 |
parent | 13725:c51140dfbc4e |
child | 13740:4cf2caa63277 |
comparison
equal
deleted
inserted
replaced
13737:46e7cc4de5e6 | 13738:26a0f653793e |
---|---|
242 module:add_item("shell-command", { | 242 module:add_item("shell-command", { |
243 section = "invite"; | 243 section = "invite"; |
244 section_desc = "Create and manage invitations"; | 244 section_desc = "Create and manage invitations"; |
245 name = "create_account"; | 245 name = "create_account"; |
246 desc = "Create an invitation to make an account on this server with the specified JID (supply only a hostname to allow any username)"; | 246 desc = "Create an invitation to make an account on this server with the specified JID (supply only a hostname to allow any username)"; |
247 args = { | |
248 { name = "user_jid", type = "string" }; | |
249 }; | |
250 host_selector = "user_jid"; | |
251 flags = { | |
252 array_params = { role = true, group = true }; | |
253 value_params = { expires_after = true }; | |
254 }; | |
255 | |
256 handler = function (self, user_jid, opts) --luacheck: ignore 212/self | |
257 local username = jid_split(user_jid); | |
258 local roles = opts.role or {}; | |
259 local groups = opts.group or {}; | |
260 | |
261 if opts.admin then | |
262 -- Insert it first since we don't get order out of argparse | |
263 table.insert(roles, 1, "prosody:admin"); | |
264 end | |
265 | |
266 local ttl; | |
267 if opts.expires_after then | |
268 ttl = human_io.parse_duration(opts.expires_after); | |
269 if not ttl then | |
270 return false, "Unable to parse duration: "..opts.expires_after; | |
271 end | |
272 end | |
273 | |
274 local invite = assert(create_account(username, { | |
275 roles = roles; | |
276 groups = groups; | |
277 }, ttl)); | |
278 | |
279 return true, invite.landing_page or invite.uri; | |
280 end; | |
281 }); | |
282 | |
283 module:add_item("shell-command", { | |
284 section = "invite"; | |
285 section_desc = "Create and manage invitations"; | |
286 name = "create_reset"; | |
287 desc = "Create a password reset link for the specified user"; | |
247 args = { { name = "user_jid", type = "string" } }; | 288 args = { { name = "user_jid", type = "string" } }; |
248 host_selector = "user_jid"; | 289 host_selector = "user_jid"; |
249 | 290 flags = { |
250 handler = function (self, user_jid) --luacheck: ignore 212/self | 291 value_params = { expires_after = true }; |
292 }; | |
293 | |
294 handler = function (self, user_jid, opts) --luacheck: ignore 212/self | |
251 local username = jid_split(user_jid); | 295 local username = jid_split(user_jid); |
252 local invite, err = create_account(username); | 296 if not username then |
253 if not invite then return nil, err; end | 297 return nil, "Supply the JID of the account you want to generate a password reset for"; |
254 return true, invite.landing_page or invite.uri; | 298 end |
255 end; | 299 local duration_sec = require "prosody.util.human.io".parse_duration(opts and opts.expires_after or "1d"); |
256 }); | 300 if not duration_sec then |
257 | 301 return nil, "Unable to parse duration: "..opts.expires_after; |
258 module:add_item("shell-command", { | 302 end |
259 section = "invite"; | |
260 section_desc = "Create and manage invitations"; | |
261 name = "create_reset"; | |
262 desc = "Create a password reset link for the specified user"; | |
263 args = { { name = "user_jid", type = "string" }, { name = "duration", type = "string" } }; | |
264 host_selector = "user_jid"; | |
265 | |
266 handler = function (self, user_jid, duration) --luacheck: ignore 212/self | |
267 local username = jid_split(user_jid); | |
268 local duration_sec = require "prosody.util.human.io".parse_duration(duration or "1d"); | |
269 local invite, err = create_account_reset(username, duration_sec); | 303 local invite, err = create_account_reset(username, duration_sec); |
270 if not invite then return nil, err; end | 304 if not invite then return nil, err; end |
271 self.session.print(invite.landing_page or invite.uri); | 305 self.session.print(invite.landing_page or invite.uri); |
272 return true, ("Password reset link for %s valid until %s"):format(user_jid, os.date("%Y-%m-%d %T", invite.expires)); | 306 return true, ("Password reset link for %s valid until %s"):format(user_jid, os.date("%Y-%m-%d %T", invite.expires)); |
273 end; | 307 end; |
276 module:add_item("shell-command", { | 310 module:add_item("shell-command", { |
277 section = "invite"; | 311 section = "invite"; |
278 section_desc = "Create and manage invitations"; | 312 section_desc = "Create and manage invitations"; |
279 name = "create_contact"; | 313 name = "create_contact"; |
280 desc = "Create an invitation to become contacts with the specified user"; | 314 desc = "Create an invitation to become contacts with the specified user"; |
281 args = { { name = "user_jid", type = "string" }, { name = "allow_registration" } }; | 315 args = { { name = "user_jid", type = "string" } }; |
282 host_selector = "user_jid"; | 316 host_selector = "user_jid"; |
283 | 317 flags = { |
284 handler = function (self, user_jid, allow_registration) --luacheck: ignore 212/self | 318 value_params = { expires_after = true }; |
319 kv_params = { allow_registration = true }; | |
320 }; | |
321 | |
322 handler = function (self, user_jid, opts) --luacheck: ignore 212/self | |
285 local username = jid_split(user_jid); | 323 local username = jid_split(user_jid); |
286 local invite, err = create_contact(username, allow_registration); | 324 if not username then |
325 return nil, "Supply the JID of the account you want the recipient to become a contact of"; | |
326 end | |
327 local ttl; | |
328 if opts.expires_after then | |
329 ttl = require "prosody.util.human.io".parse_duration(opts.expires_after); | |
330 if not ttl then | |
331 return nil, "Unable to parse duration: "..opts.expires_after; | |
332 end | |
333 end | |
334 local invite, err = create_contact(username, opts.allow_registration, nil, ttl); | |
287 if not invite then return nil, err; end | 335 if not invite then return nil, err; end |
288 return true, invite.landing_page or invite.uri; | 336 return true, invite.landing_page or invite.uri; |
289 end; | 337 end; |
290 }); | 338 }); |
291 | 339 |
440 return 2; | 488 return 2; |
441 end | 489 end |
442 return subcommands[cmd](arg); | 490 return subcommands[cmd](arg); |
443 end | 491 end |
444 | 492 |
445 function subcommands.generate(arg) | 493 function subcommands.generate() |
446 local function help(short) | 494 print("This command is deprecated. Please see 'prosodyctl shell help invite' for available commands."); |
447 print("usage: prosodyctl mod_" .. module.name .. " generate DOMAIN --reset USERNAME") | 495 return 1; |
448 print("usage: prosodyctl mod_" .. module.name .. " generate DOMAIN [--admin] [--role ROLE] [--group GROUPID]...") | 496 end |
449 if short then return 2 end | |
450 print() | |
451 print("This command has two modes: password reset and new account.") | |
452 print("If --reset is given, the command operates in password reset mode and in new account mode otherwise.") | |
453 print() | |
454 print("required arguments in password reset mode:") | |
455 print() | |
456 print(" --reset USERNAME Generate a password reset link for the given USERNAME.") | |
457 print() | |
458 print("optional arguments in new account mode:") | |
459 print() | |
460 print(" --admin Make the new user privileged") | |
461 print(" Equivalent to --role prosody:admin") | |
462 print(" --role ROLE Grant the given ROLE to the new user") | |
463 print(" --group GROUPID Add the user to the group with the given ID") | |
464 print(" Can be specified multiple times") | |
465 print(" --expires-after T Time until the invite expires (e.g. '1 week')") | |
466 print() | |
467 print("--group can be specified multiple times; the user will be added to all groups.") | |
468 print() | |
469 print("--reset and the other options cannot be mixed.") | |
470 return 2 | |
471 end | |
472 | |
473 local earlyopts = argparse.parse(arg, { short_params = { h = "help"; ["?"] = "help" } }); | |
474 if earlyopts.help or not earlyopts[1] then | |
475 return help(); | |
476 end | |
477 | |
478 local sm = require "prosody.core.storagemanager"; | |
479 local mm = require "prosody.core.modulemanager"; | |
480 | |
481 local host = table.remove(arg, 1); -- pop host | |
482 if not host then return help(true) end | |
483 sm.initialize_host(host); | |
484 module.host = host; --luacheck: ignore 122/module | |
485 token_storage = module:open_store("invite_token", "map"); | |
486 | |
487 local opts = argparse.parse(arg, { | |
488 short_params = { h = "help"; ["?"] = "help"; g = "group" }; | |
489 value_params = { group = true; reset = true; role = true }; | |
490 array_params = { group = true; role = true }; | |
491 }); | |
492 | |
493 if opts.help then | |
494 return help(); | |
495 end | |
496 | |
497 -- Load mod_invites | |
498 local invites = module:depends("invites"); | |
499 -- Optional community module that if used, needs to be loaded here | |
500 local invites_page_module = module:get_option_string("invites_page_module", "invites_page"); | |
501 if mm.get_modules_for_host(host):contains(invites_page_module) then | |
502 module:depends(invites_page_module); | |
503 end | |
504 | |
505 local allow_reset; | |
506 | |
507 if opts.reset then | |
508 local nodeprep = require "prosody.util.encodings".stringprep.nodeprep; | |
509 local username = nodeprep(opts.reset) | |
510 if not username then | |
511 print("Please supply a valid username to generate a reset link for"); | |
512 return 2; | |
513 end | |
514 allow_reset = username; | |
515 end | |
516 | |
517 local roles = opts.role or {}; | |
518 local groups = opts.group or {}; | |
519 | |
520 if opts.admin then | |
521 -- Insert it first since we don't get order out of argparse | |
522 table.insert(roles, 1, "prosody:admin"); | |
523 end | |
524 | |
525 local invite; | |
526 if allow_reset then | |
527 if roles[1] then | |
528 print("--role/--admin and --reset are mutually exclusive") | |
529 return 2; | |
530 end | |
531 if #groups > 0 then | |
532 print("--group and --reset are mutually exclusive") | |
533 end | |
534 invite = assert(invites.create_account_reset(allow_reset)); | |
535 else | |
536 invite = assert(invites.create_account(nil, { | |
537 roles = roles, | |
538 groups = groups | |
539 }, opts.expires_after and human_io.parse_duration(opts.expires_after))); | |
540 end | |
541 | |
542 print(invite.landing_page or invite.uri); | |
543 end |