author | Matthew Wild <mwild1@gmail.com> |
Thu, 30 Nov 2023 17:59:08 +0000 | |
changeset 5749 | 628952e4ff47 |
parent 5147 | 1cae382e88a1 |
permissions | -rw-r--r-- |
4119
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 |
5147
1cae382e88a1
mod_invites_api: Fix traceback when no query params (thanks Menel)
Matthew Wild <mwild1@gmail.com>
parents:
5146
diff
changeset
|
18 |
params = params or http_formdecode(request.url.query or "="); |
4119
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 |
|
4220
35b678609b79
mod_invites_api: Allow restricting HTTP methods per key (once implemented)
Matthew Wild <mwild1@gmail.com>
parents:
4119
diff
changeset
|
57 |
if api_user.allowed_methods and not api_user.allowed_methods[event.request.method] then |
35b678609b79
mod_invites_api: Allow restricting HTTP methods per key (once implemented)
Matthew Wild <mwild1@gmail.com>
parents:
4119
diff
changeset
|
58 |
return 405; |
35b678609b79
mod_invites_api: Allow restricting HTTP methods per key (once implemented)
Matthew Wild <mwild1@gmail.com>
parents:
4119
diff
changeset
|
59 |
end |
35b678609b79
mod_invites_api: Allow restricting HTTP methods per key (once implemented)
Matthew Wild <mwild1@gmail.com>
parents:
4119
diff
changeset
|
60 |
|
4119
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
61 |
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
|
62 |
if not invite then |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
63 |
return 500; |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
64 |
end |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
65 |
|
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
66 |
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
|
67 |
|
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
68 |
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
|
69 |
return 303; |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
70 |
end |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
71 |
return 201; |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
72 |
end |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
73 |
|
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
74 |
if invites then |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
75 |
module:provides("http", { |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
76 |
route = { |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
77 |
["GET"] = handle_request; |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
78 |
}; |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
79 |
}); |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
80 |
end |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
81 |
|
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
82 |
function module.command(arg) |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
83 |
if #arg < 2 then |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
84 |
print("Usage:"); |
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 |
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
|
87 |
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
|
88 |
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
|
89 |
print(""); |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
90 |
end |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
91 |
|
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
92 |
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
|
93 |
|
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
94 |
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
|
95 |
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
|
96 |
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
|
97 |
return 1; |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
98 |
end |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
99 |
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
|
100 |
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
|
101 |
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
|
102 |
|
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
103 |
if command == "create" then |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
104 |
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
|
105 |
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
|
106 |
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
|
107 |
id = id; |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
108 |
token = token; |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
109 |
name = arg[1]; |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
110 |
created_at = os.time(); |
4220
35b678609b79
mod_invites_api: Allow restricting HTTP methods per key (once implemented)
Matthew Wild <mwild1@gmail.com>
parents:
4119
diff
changeset
|
111 |
allowed_methods = { GET = true, POST = true }; |
4119
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
112 |
}); |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
113 |
print(id.."/"..token); |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
114 |
elseif command == "delete" then |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
115 |
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
|
116 |
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
|
117 |
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
|
118 |
return 1; |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
119 |
end |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
120 |
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
|
121 |
elseif command == "list" then |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
122 |
local api_key_store_kv = module:open_store("invite_api_keys"); |
5146
410d7c8d210d
mod_invites_api: Fix traceback on list command with no entries (thanks mirux)
Matthew Wild <mwild1@gmail.com>
parents:
4220
diff
changeset
|
123 |
for key_id, key_info in pairs(api_key_store_kv:get(nil) or {}) do |
4119
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
124 |
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
|
125 |
end |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
126 |
else |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
127 |
print("Unknown command - "..command); |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
128 |
end |
165ade4ce97b
mod_invites_api: New module to create new invites over HTTP
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
129 |
end |