annotate mod_invites_api/mod_invites_api.lua @ 4203:c4002aae4ad3

mod_s2s_keepalive: Use timestamp as iq @id RFC 6120 implies that the id attribute must be unique within a stream. This should fix problems with remote servers that enforce uniqueness and don't answer duplicated ids. If it doesn't do that, then at least you can get a guesstimate at round-trip time from the difference between the result iq stanza and the timestamp it was logged without having to go look for when it was sent, or needing to keep state.
author Kim Alvefur <zash@zash.se>
date Wed, 14 Oct 2020 18:02:10 +0200
parents 165ade4ce97b
children 35b678609b79
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
4115
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
1 local http_formdecode = require "net.http".formdecode;
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
2
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
3 local api_key_store;
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
4 local invites;
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
5 -- COMPAT: workaround to avoid executing inside prosodyctl
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
6 if prosody.shutdown then
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
7 module:depends("http");
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
8 api_key_store = module:open_store("invite_api_keys", "map");
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
9 invites = module:depends("invites");
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
10 end
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
11
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
12 local function get_api_user(request, params)
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
13 local combined_key;
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
14
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
15 local auth_header = request.headers.authorization;
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
16
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
17 if not auth_header then
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
18 params = params or http_formdecode(request.url.query);
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
19 combined_key = params.key;
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
20 else
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
21 local auth_type, value = auth_header:match("^(%S+)%s(%S+)$");
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
22 if auth_type ~= "Bearer" then
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
23 return;
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
24 end
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
25 combined_key = value;
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
26 end
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
27
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
28 if not combined_key then
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
29 return;
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
30 end
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
31
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
32 local key_id, key_token = combined_key:match("^([^/]+)/(.+)$");
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
33
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
34 if not key_id then
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
35 return;
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
36 end
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
37
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
38 local api_user = api_key_store:get(nil, key_id);
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
39
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
40 if not api_user or api_user.token ~= key_token then
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
41 return;
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
42 end
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
43
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
44 -- TODO: key expiry, rate limiting, etc.
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
45 return api_user;
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
46 end
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
47
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
48 function handle_request(event)
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
49 local query_params = http_formdecode(event.request.url.query);
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
50
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
51 local api_user = get_api_user(event.request, query_params);
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
52
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
53 if not api_user then
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
54 return 403;
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
55 end
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
56
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
57 local invite = invites.create_account(nil, { source = "api/token/"..api_user.id });
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
58 if not invite then
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
59 return 500;
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
60 end
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
61
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
62 event.response.headers.Location = invite.landing_page or invite.uri;
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
63
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
64 if query_params.redirect then
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
65 return 303;
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
66 end
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
67 return 201;
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
68 end
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
69
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
70 if invites then
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
71 module:provides("http", {
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
72 route = {
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
73 ["GET"] = handle_request;
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
74 };
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
75 });
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
76 end
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
77
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
78 function module.command(arg)
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
79 if #arg < 2 then
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
80 print("Usage:");
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
81 print("");
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
82 print(" prosodyctl mod_"..module.name.." create NAME");
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
83 print(" prosodyctl mod_"..module.name.." delete KEY_ID");
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
84 print(" prosodyctl mod_"..module.name.." list");
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
85 print("");
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
86 end
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
87
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
88 local command = table.remove(arg, 1);
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
89
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
90 local host = table.remove(arg, 1);
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
91 if not prosody.hosts[host] then
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
92 print("Error: please supply a valid host");
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
93 return 1;
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
94 end
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
95 require "core.storagemanager".initialize_host(host);
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
96 module.host = host; --luacheck: ignore 122/module
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
97 api_key_store = module:open_store("invite_api_keys", "map");
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
98
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
99 if command == "create" then
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
100 local id = require "util.id".short();
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
101 local token = require "util.id".long();
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
102 api_key_store:set(nil, id, {
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
103 id = id;
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
104 token = token;
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
105 name = arg[1];
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
106 created_at = os.time();
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
107 });
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
108 print(id.."/"..token);
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
109 elseif command == "delete" then
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
110 local id = table.remove(arg, 1);
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
111 if not api_key_store:get(nil, id) then
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
112 print("Error: key not found");
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
113 return 1;
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
114 end
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
115 api_key_store:set(nil, id, nil);
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
116 elseif command == "list" then
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
117 local api_key_store_kv = module:open_store("invite_api_keys");
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
118 for key_id, key_info in pairs(api_key_store_kv:get(nil)) do
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
119 print(key_id, key_info.name or "<unknown>");
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
120 end
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
121 else
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
122 print("Unknown command - "..command);
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
123 end
165ade4ce97b mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
124 end