Software /
code /
prosody
Comparison
plugins/mod_http_file_share.lua @ 11321:15ab878a7d23
mod_http_file_share: Add some logging
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Wed, 27 Jan 2021 17:29:26 +0100 |
parent | 11320:817cadf6be92 |
child | 11322:4ade9810ce35 |
comparison
equal
deleted
inserted
replaced
11320:817cadf6be92 | 11321:15ab878a7d23 |
---|---|
13 local url = require "socket.url"; | 13 local url = require "socket.url"; |
14 local dm = require "core.storagemanager".olddm; | 14 local dm = require "core.storagemanager".olddm; |
15 local jwt = require "util.jwt"; | 15 local jwt = require "util.jwt"; |
16 local errors = require "util.error"; | 16 local errors = require "util.error"; |
17 local dataform = require "util.dataforms".new; | 17 local dataform = require "util.dataforms".new; |
18 local dt = require "util.datetime"; | |
19 local hi = require "util.human.units"; | |
18 | 20 |
19 local namespace = "urn:xmpp:http:upload:0"; | 21 local namespace = "urn:xmpp:http:upload:0"; |
20 | 22 |
21 module:depends("disco"); | 23 module:depends("disco"); |
22 | 24 |
49 filesize = { type = "modify"; condition = "not-acceptable"; text = "File too large"; | 51 filesize = { type = "modify"; condition = "not-acceptable"; text = "File too large"; |
50 extra = {tag = st.stanza("file-too-large", {xmlns = namespace}):tag("max-file-size"):text(tostring(file_size_limit)) }; | 52 extra = {tag = st.stanza("file-too-large", {xmlns = namespace}):tag("max-file-size"):text(tostring(file_size_limit)) }; |
51 filesizefmt = { type = "modify"; condition = "bad-request"; text = "File size must be positive integer"; } | 53 filesizefmt = { type = "modify"; condition = "bad-request"; text = "File size must be positive integer"; } |
52 }; | 54 }; |
53 }); | 55 }); |
56 | |
57 -- Convenience wrapper for logging file sizes | |
58 local function B(bytes) return hi.format(bytes, "B", "b"); end | |
54 | 59 |
55 function may_upload(uploader, filename, filesize, filetype) -- > boolean, error | 60 function may_upload(uploader, filename, filesize, filetype) -- > boolean, error |
56 local uploader_host = jid.host(uploader); | 61 local uploader_host = jid.host(uploader); |
57 if not ((access:empty() and prosody.hosts[uploader_host]) or access:contains(uploader) or access:contains(uploader_host)) then | 62 if not ((access:empty() and prosody.hosts[uploader_host]) or access:contains(uploader) or access:contains(uploader_host)) then |
58 return false, upload_errors.new("access"); | 63 return false, upload_errors.new("access"); |
116 if not may then | 121 if not may then |
117 origin.send(st.error_reply(stanza, why_not)); | 122 origin.send(st.error_reply(stanza, why_not)); |
118 return true; | 123 return true; |
119 end | 124 end |
120 | 125 |
126 module:log("info", "Issuing upload slot to %s for %s", uploader, B(filesize)); | |
121 local slot, storage_err = errors.coerce(uploads:append(nil, nil, request, os.time(), uploader)) | 127 local slot, storage_err = errors.coerce(uploads:append(nil, nil, request, os.time(), uploader)) |
122 if not slot then | 128 if not slot then |
123 origin.send(st.error_reply(stanza, storage_err)); | 129 origin.send(st.error_reply(stanza, storage_err)); |
124 return true; | 130 return true; |
125 end | 131 end |
141 | 147 |
142 function handle_upload(event, path) -- PUT /upload/:slot | 148 function handle_upload(event, path) -- PUT /upload/:slot |
143 local request = event.request; | 149 local request = event.request; |
144 local authz = request.headers.authorization; | 150 local authz = request.headers.authorization; |
145 if not authz or not authz:find"^Bearer ." then | 151 if not authz or not authz:find"^Bearer ." then |
152 module:log("debug", "Missing Authorization"); | |
146 return 403; | 153 return 403; |
147 end | 154 end |
148 local authed, upload_info = jwt.verify(secret, authz:match("^Bearer (.*)")); | 155 local authed, upload_info = jwt.verify(secret, authz:match("^Bearer (.*)")); |
149 if not (authed and type(upload_info) == "table" and type(upload_info.exp) == "number") then | 156 if not (authed and type(upload_info) == "table" and type(upload_info.exp) == "number") then |
157 module:log("debug", "Unauthorized or invalid token: %s, %q", authed, upload_info); | |
150 return 401; | 158 return 401; |
151 end | 159 end |
152 if upload_info.exp < os.time() then | 160 if upload_info.exp < os.time() then |
161 module:log("debug", "Authorization token expired on %s", dt.datetime(upload_info.exp)); | |
153 return 410; | 162 return 410; |
154 end | 163 end |
155 if not path or upload_info.slot ~= path:match("^[^/]+") then | 164 if not path or upload_info.slot ~= path:match("^[^/]+") then |
165 module:log("debug", "Invalid upload slot: %q, path: %q", upload_info.slot, path); | |
156 return 400; | 166 return 400; |
157 end | 167 end |
158 | 168 |
159 local filename = dm.getpath(upload_info.slot, module.host, module.name, nil, true); | 169 local filename = dm.getpath(upload_info.slot, module.host, module.name, nil, true); |
160 | 170 |
161 if not request.body_sink then | 171 if not request.body_sink then |
172 module:log("debug", "Preparing to receive upload into %q, expecting %s", filename, B(upload_info.filesize)); | |
162 local fh, err = errors.coerce(io.open(filename.."~", "w")); | 173 local fh, err = errors.coerce(io.open(filename.."~", "w")); |
163 if not fh then | 174 if not fh then |
164 return err; | 175 return err; |
165 end | 176 end |
166 request.body_sink = fh; | 177 request.body_sink = fh; |
168 return true; | 179 return true; |
169 end | 180 end |
170 end | 181 end |
171 | 182 |
172 if request.body then | 183 if request.body then |
184 module:log("debug", "Complete upload available, %s", B(#request.body)); | |
185 -- Small enough to have been uploaded already | |
173 local written, err = errors.coerce(request.body_sink:write(request.body)); | 186 local written, err = errors.coerce(request.body_sink:write(request.body)); |
174 if not written then | 187 if not written then |
175 return err; | 188 return err; |
176 end | 189 end |
177 request.body = nil; | 190 request.body = nil; |
183 if final_size ~= upload_info.filesize then | 196 if final_size ~= upload_info.filesize then |
184 -- Could be too short as well, but we say the same thing | 197 -- Could be too short as well, but we say the same thing |
185 uploaded, err = false, 413; | 198 uploaded, err = false, 413; |
186 end | 199 end |
187 if uploaded then | 200 if uploaded then |
201 module:log("debug", "Upload of %q completed, %s", filename, B(final_size)); | |
188 assert(os.rename(filename.."~", filename)); | 202 assert(os.rename(filename.."~", filename)); |
189 return 201; | 203 return 201; |
190 else | 204 else |
191 assert(os.remove(filename.."~")); | 205 assert(os.remove(filename.."~")); |
192 return err; | 206 return err; |