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