Software /
code /
prosody-modules
Comparison
mod_storage_s3/mod_storage_s3.lua @ 5759:ba731ff5b895
mod_storage_s3: Reorder path components (BC: invalidates any existing data)
keyvalue: /bucket/hostname/username/store
archive: /bucket/hostname/username/store/yyyy-mm-dd/with/key
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Mon, 27 Nov 2023 09:30:04 +0100 |
parent | 5758:9a1d8c39d0b0 |
child | 5760:72b0fa7e36dc |
comparison
equal
deleted
inserted
replaced
5758:9a1d8c39d0b0 | 5759:ba731ff5b895 |
---|---|
153 function keyval:_path(key) | 153 function keyval:_path(key) |
154 return url.build_path({ | 154 return url.build_path({ |
155 is_absolute = true; | 155 is_absolute = true; |
156 bucket; | 156 bucket; |
157 jid.escape(module.host); | 157 jid.escape(module.host); |
158 jid.escape(key or "@"); | |
158 jid.escape(self.store); | 159 jid.escape(self.store); |
159 jid.escape(key or "@"); | |
160 }) | 160 }) |
161 end | 161 end |
162 | 162 |
163 function keyval:get(user) | 163 function keyval:get(user) |
164 return async.wait_for(new_request(self, "GET", self:_path(user)):next(on_result)); | 164 return async.wait_for(new_request(self, "GET", self:_path(user)):next(on_result)); |
173 return async.wait_for(new_request(self, "PUT", self:_path(user), nil, data)); | 173 return async.wait_for(new_request(self, "PUT", self:_path(user), nil, data)); |
174 end | 174 end |
175 | 175 |
176 function keyval:users() | 176 function keyval:users() |
177 local bucket_path = url.build_path({ is_absolute = true; bucket; is_directory = true }); | 177 local bucket_path = url.build_path({ is_absolute = true; bucket; is_directory = true }); |
178 local prefix = url.build_path({ jid.escape(module.host); jid.escape(self.store); is_directory = true }); | 178 local prefix = url.build_path({ jid.escape(module.host); is_directory = true }); |
179 local list_result, err = async.wait_for(new_request(self, "GET", bucket_path, { prefix = prefix })) | 179 local list_result, err = async.wait_for(new_request(self, "GET", bucket_path, { prefix = prefix })) |
180 if err or list_result.code ~= 200 then | 180 if err or list_result.code ~= 200 then |
181 return nil, err; | 181 return nil, err; |
182 end | 182 end |
183 local list_bucket_result = xml.parse(list_result.body); | 183 local list_bucket_result = xml.parse(list_result.body); |
184 if list_bucket_result:get_child_text("IsTruncated") == "true" then | 184 if list_bucket_result:get_child_text("IsTruncated") == "true" then |
185 local max_keys = list_bucket_result:get_child_text("MaxKeys"); | 185 local max_keys = list_bucket_result:get_child_text("MaxKeys"); |
186 module:log("warn", "Paging truncated results not implemented, max %s %s returned", max_keys, self.store); | 186 module:log("warn", "Paging truncated results not implemented, max %s %s returned", max_keys, self.store); |
187 end | 187 end |
188 local keys = array(); | 188 local keys = array(); |
189 local store_part = jid.escape(self.store); | |
189 for content in list_bucket_result:childtags("Contents") do | 190 for content in list_bucket_result:childtags("Contents") do |
190 local key = url.parse_path(content:get_child_text("Key")); | 191 local key = url.parse_path(content:get_child_text("Key")); |
191 keys:push(jid.unescape(key[3])); | 192 if key[3] == store_part then |
193 keys:push(jid.unescape(key[2])); | |
194 end | |
192 end | 195 end |
193 return function() | 196 return function() |
194 return keys:pop(); | 197 return keys:pop(); |
195 end | 198 end |
196 end | 199 end |
206 function archive:_path(username, date, when, with, key) | 209 function archive:_path(username, date, when, with, key) |
207 return url.build_path({ | 210 return url.build_path({ |
208 is_absolute = true; | 211 is_absolute = true; |
209 bucket; | 212 bucket; |
210 jid.escape(module.host); | 213 jid.escape(module.host); |
214 jid.escape(username or "@"); | |
211 jid.escape(self.store); | 215 jid.escape(self.store); |
212 jid.escape(username or "@"); | 216 date or dt.date(when); |
213 jid.escape(with and jid.prep(with) or "@"); | 217 jid.escape(with and jid.prep(with) or "@"); |
214 date or dt.date(when); | |
215 key; | 218 key; |
216 }) | 219 }) |
217 end | 220 end |
218 | 221 |
219 | 222 |
233 end)); | 236 end)); |
234 end | 237 end |
235 | 238 |
236 function archive:find(username, query) | 239 function archive:find(username, query) |
237 local bucket_path = url.build_path({ is_absolute = true; bucket; is_directory = true }); | 240 local bucket_path = url.build_path({ is_absolute = true; bucket; is_directory = true }); |
238 local prefix = { jid.escape(module.host); jid.escape(self.store); is_directory = true }; | 241 local prefix = { jid.escape(module.host); jid.escape(username or "@"); jid.escape(self.store); is_directory = true }; |
239 table.insert(prefix, jid.escape(username or "@")); | |
240 if not query then | 242 if not query then |
241 query = {}; | 243 query = {}; |
242 end | 244 end |
243 if query["with"] then | 245 |
244 table.insert(prefix, jid.escape(jid.prep(query["with"]), true):sub(1,24)); | 246 if query["start"] and query["end"] and dt.date(query["start"]) == dt.date(query["end"]) then |
245 if query["start"] and query["end"] and dt.date(query["start"]) == dt.date(query["end"]) then | 247 table.insert(prefix, dt.date(query["start"])); |
246 table.insert(prefix, dt.date(query["start"])); | 248 if query["with"] then |
249 table.insert(prefix, jid.escape(query["with"])); | |
247 end | 250 end |
248 end | 251 end |
249 | 252 |
250 prefix = url.build_path(prefix); | 253 prefix = url.build_path(prefix); |
251 local list_result, err = async.wait_for(new_request(self, "GET", bucket_path, { | 254 local list_result, err = async.wait_for(new_request(self, "GET", bucket_path, { |
269 iterwrap = it.reverse; | 272 iterwrap = it.reverse; |
270 end | 273 end |
271 local ids = query["ids"] and set.new(query["ids"]); | 274 local ids = query["ids"] and set.new(query["ids"]); |
272 local found = not query["after"]; | 275 local found = not query["after"]; |
273 for content in iterwrap(list_bucket_result:childtags("Contents")) do | 276 for content in iterwrap(list_bucket_result:childtags("Contents")) do |
274 local key = url.parse_path(content:get_child_text("Key")); | 277 local when, with, id = table.unpack(url.parse_path(content:get_child_text("Key")), 4); |
275 if found and query["before"] == key[6] then | 278 with = jid.unescape(with); |
279 if found and query["before"] == id then | |
276 break | 280 break |
277 end | 281 end |
278 if (not query["with"] or query["with"] == jid.unescape(key[5])) | 282 if (not query["with"] or query["with"] == with) |
279 and (not query["start"] or dt.date(query["start"]) >= key[6]) | 283 and (not query["start"] or dt.date(query["start"]) >= when) |
280 and (not query["end"] or dt.date(query["end"]) <= key[6]) | 284 and (not query["end"] or dt.date(query["end"]) <= when) |
281 and (not ids or ids:contains(key[6])) | 285 and (not ids or ids:contains(id)) |
282 and found then | 286 and found then |
283 keys:push({ key = key[6]; date = key[5]; with = jid.unescape(key[4]) }); | 287 keys:push({ key = id; date = when; with = with }); |
284 end | 288 end |
285 if not found and key[6] == query["after"] then | 289 if not found and id == query["after"] then |
286 found = not found | 290 found = not found |
287 end | 291 end |
288 end | 292 end |
289 local i = 0; | 293 local i = 0; |
290 local function get_next() | 294 local function get_next() |