Software /
code /
prosody
Comparison
plugins/mod_invites.lua @ 13161:9ba11ef91ce4
mod_invites: Refactor argument handling using util.argparse
This makes it so that --admin and --role are no longer mutually
exclusive, they the former is simply treated as another --role.
This was likely a leftover from when only a single role was possible.
It does however become unclear which should be the primary, since the
order is not preserved by argparse.
Bonus: Loading of modules is avoided with only the --help is shown.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Wed, 12 Jan 2022 10:23:13 +0100 |
parent | 13096:9638ff8b1c81 |
child | 13209:c8d949cf6b09 |
comparison
equal
deleted
inserted
replaced
13160:4ee9a912ceea | 13161:9ba11ef91ce4 |
---|---|
1 local id = require "prosody.util.id"; | 1 local id = require "prosody.util.id"; |
2 local it = require "prosody.util.iterators"; | 2 local it = require "prosody.util.iterators"; |
3 local url = require "socket.url"; | 3 local url = require "socket.url"; |
4 local jid_node = require "prosody.util.jid".node; | 4 local jid_node = require "prosody.util.jid".node; |
5 local jid_split = require "prosody.util.jid".split; | 5 local jid_split = require "prosody.util.jid".split; |
6 local argparse = require "prosody.util.argparse"; | |
6 | 7 |
7 local default_ttl = module:get_option_number("invite_expiry", 86400 * 7); | 8 local default_ttl = module:get_option_number("invite_expiry", 86400 * 7); |
8 | 9 |
9 local token_storage; | 10 local token_storage; |
10 if prosody.process_type == "prosody" or prosody.shutdown then | 11 if prosody.process_type == "prosody" or prosody.shutdown then |
228 if not invite then return nil, err; end | 229 if not invite then return nil, err; end |
229 return true, invite.landing_page or invite.uri; | 230 return true, invite.landing_page or invite.uri; |
230 end | 231 end |
231 end | 232 end |
232 | 233 |
234 local subcommands = {}; | |
235 | |
233 --- prosodyctl command | 236 --- prosodyctl command |
234 function module.command(arg) | 237 function module.command(arg) |
235 if #arg < 2 or arg[1] ~= "generate" then | 238 local opts = argparse.parse(arg, { short_params = { h = "help"; ["?"] = "help" } }); |
239 local cmd = table.remove(arg, 1); -- pop command | |
240 if opts.help or not cmd or not subcommands[cmd] then | |
236 print("usage: prosodyctl mod_"..module.name.." generate example.com"); | 241 print("usage: prosodyctl mod_"..module.name.." generate example.com"); |
237 return 2; | 242 return 2; |
238 end | 243 end |
239 table.remove(arg, 1); -- pop command | 244 return subcommands[cmd](arg); |
245 end | |
246 | |
247 function subcommands.generate(arg) | |
240 | 248 |
241 local sm = require "prosody.core.storagemanager"; | 249 local sm = require "prosody.core.storagemanager"; |
242 local mm = require "prosody.core.modulemanager"; | 250 local mm = require "prosody.core.modulemanager"; |
243 | 251 |
244 local host = arg[1]; | 252 local host = table.remove(arg, 1); -- pop host |
245 assert(prosody.hosts[host], "Host "..tostring(host).." does not exist"); | 253 assert(prosody.hosts[host], "Host "..tostring(host).." does not exist"); |
246 sm.initialize_host(host); | 254 sm.initialize_host(host); |
247 table.remove(arg, 1); -- pop host | |
248 module.host = host; --luacheck: ignore 122/module | 255 module.host = host; --luacheck: ignore 122/module |
249 token_storage = module:open_store("invite_token", "map"); | 256 token_storage = module:open_store("invite_token", "map"); |
257 | |
258 local opts = argparse.parse(arg, { | |
259 short_params = { h = "help"; ["?"] = "help"; g = "group" }; | |
260 value_params = { group = true; reset = true; role = true }; | |
261 array_params = { group = true; role = true }; | |
262 }); | |
263 | |
264 | |
265 if opts.help then | |
266 print("usage: prosodyctl mod_" .. module.name .. " generate DOMAIN --reset USERNAME") | |
267 print("usage: prosodyctl mod_" .. module.name .. " generate DOMAIN [--admin] [--role ROLE] [--group GROUPID]...") | |
268 print() | |
269 print("This command has two modes: password reset and new account.") | |
270 print("If --reset is given, the command operates in password reset mode and in new account mode otherwise.") | |
271 print() | |
272 print("required arguments in password reset mode:") | |
273 print() | |
274 print(" --reset USERNAME Generate a password reset link for the given USERNAME.") | |
275 print() | |
276 print("optional arguments in new account mode:") | |
277 print() | |
278 print(" --admin Make the new user privileged") | |
279 print(" Equivalent to --role prosody:admin") | |
280 print(" --role ROLE Grant the given ROLE to the new user") | |
281 print(" --group GROUPID Add the user to the group with the given ID") | |
282 print(" Can be specified multiple times") | |
283 print() | |
284 print("--group can be specified multiple times; the user will be added to all groups.") | |
285 print() | |
286 print("--reset and the other options cannot be mixed.") | |
287 return 2 | |
288 end | |
250 | 289 |
251 -- Load mod_invites | 290 -- Load mod_invites |
252 local invites = module:depends("invites"); | 291 local invites = module:depends("invites"); |
253 -- Optional community module that if used, needs to be loaded here | 292 -- Optional community module that if used, needs to be loaded here |
254 local invites_page_module = module:get_option_string("invites_page_module", "invites_page"); | 293 local invites_page_module = module:get_option_string("invites_page_module", "invites_page"); |
255 if mm.get_modules_for_host(host):contains(invites_page_module) then | 294 if mm.get_modules_for_host(host):contains(invites_page_module) then |
256 module:depends(invites_page_module); | 295 module:depends(invites_page_module); |
257 end | 296 end |
258 | 297 |
259 local allow_reset; | 298 local allow_reset; |
260 local roles = {}; | 299 |
261 local groups = {}; | 300 if opts.reset then |
262 | 301 local nodeprep = require "prosody.util.encodings".stringprep.nodeprep; |
263 while #arg > 0 do | 302 local username = nodeprep(opts.reset) |
264 local value = arg[1]; | 303 if not username then |
265 table.remove(arg, 1); | 304 print("Please supply a valid username to generate a reset link for"); |
266 if value == "--help" then | 305 return 2; |
267 print("usage: prosodyctl mod_"..module.name.." generate DOMAIN --reset USERNAME") | 306 end |
268 print("usage: prosodyctl mod_"..module.name.." generate DOMAIN [--admin] [--role ROLE] [--group GROUPID]...") | 307 allow_reset = username; |
269 print() | 308 end |
270 print("This command has two modes: password reset and new account.") | 309 |
271 print("If --reset is given, the command operates in password reset mode and in new account mode otherwise.") | 310 local roles = opts.role or {}; |
272 print() | 311 local groups = opts.groups or {}; |
273 print("required arguments in password reset mode:") | 312 |
274 print() | 313 if opts.admin then |
275 print(" --reset USERNAME Generate a password reset link for the given USERNAME.") | 314 -- Insert it first since we don't get order out of argparse |
276 print() | 315 table.insert(roles, 1, "prosody:admin"); |
277 print("optional arguments in new account mode:") | |
278 print() | |
279 print(" --admin Make the new user privileged") | |
280 print(" Equivalent to --role prosody:admin") | |
281 print(" --role ROLE Grant the given ROLE to the new user") | |
282 print(" --group GROUPID Add the user to the group with the given ID") | |
283 print(" Can be specified multiple times") | |
284 print() | |
285 print("--role and --admin can be specified multiple times; the first role becomes the primary role, the rest become secondary roles") | |
286 print("--group can be specified multiple times; the user will be added to all groups.") | |
287 print() | |
288 print("--reset and the other options cannot be mixed.") | |
289 return 2 | |
290 elseif value == "--reset" then | |
291 local nodeprep = require "prosody.util.encodings".stringprep.nodeprep; | |
292 local username = nodeprep(arg[1]) | |
293 table.remove(arg, 1); | |
294 if not username then | |
295 print("Please supply a valid username to generate a reset link for"); | |
296 return 2; | |
297 end | |
298 allow_reset = username; | |
299 elseif value == "--admin" then | |
300 table.insert(roles, "prosody:admin"); | |
301 elseif value == "--role" then | |
302 local rolename = arg[1]; | |
303 if not rolename then | |
304 print("Please supply a role name"); | |
305 return 2; | |
306 end | |
307 table.insert(roles, rolename); | |
308 table.remove(arg, 1); | |
309 elseif value == "--group" or value == "-g" then | |
310 local groupid = arg[1]; | |
311 if not groupid then | |
312 print("Please supply a group ID") | |
313 return 2; | |
314 end | |
315 table.insert(groups, groupid); | |
316 table.remove(arg, 1); | |
317 else | |
318 print("unexpected argument: "..value) | |
319 end | |
320 end | 316 end |
321 | 317 |
322 local invite; | 318 local invite; |
323 if allow_reset then | 319 if allow_reset then |
324 if roles[1] then | 320 if roles[1] then |