Changeset

11346:315faec1a920

mod_http_file_share: Add support for daily upload quotas. Daily instead of total quotas, should be more efficient to calculate. Still O(n), but a smaller n. Less affected by total retention period.
author Kim Alvefur <zash@zash.se>
date Sun, 31 Jan 2021 14:43:42 +0100
parents 11345:0fec04b64a49
children 11347:5b3ad3c7fe47
files plugins/mod_http_file_share.lua
diffstat 1 files changed, 19 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/plugins/mod_http_file_share.lua	Sun Jan 31 14:41:56 2021 +0100
+++ b/plugins/mod_http_file_share.lua	Sun Jan 31 14:43:42 2021 +0100
@@ -35,6 +35,7 @@
 local file_types = module:get_option_set(module.name .. "_allowed_file_types", {});
 local safe_types = module:get_option_set(module.name .. "_safe_file_types", {"image/*","video/*","audio/*","text/plain"});
 local expiry = module:get_option_number(module.name .. "_expires_after", 7 * 86400);
+local daily_quota = module:get_option_number(module.name .. "_daily_quota", file_size_limit*10); -- 100 MB / day
 
 local access = module:get_option_set(module.name .. "_access", {});
 
@@ -55,6 +56,7 @@
 		extra = {tag = st.stanza("file-too-large", {xmlns = namespace}):tag("max-file-size"):text(tostring(file_size_limit)) };
 	};
 	filesizefmt = { type = "modify"; condition = "bad-request"; text = "File size must be positive integer"; };
+	quota = { type = "wait"; condition = "resource-constraint"; text = "Daily quota reached"; };
 });
 
 local upload_cache = cache.new(1024);
@@ -66,6 +68,18 @@
 	return dm.getpath(slot, module.host, module.name, "bin", create)
 end
 
+-- TODO cache
+function get_daily_quota(uploader)
+	local iter, err = uploads:find(nil, {with = uploader; start = os.time() - 86400});
+	if not iter then return iter, err; end
+	local total_bytes = 0;
+	for _, slot in iter do
+		local size = tonumber(slot.attr.size);
+		if size then total_bytes = total_bytes + size; end
+	end
+	return total_bytes;
+end
+
 function may_upload(uploader, filename, filesize, filetype) -- > boolean, error
 	local uploader_host = jid.host(uploader);
 	if not ((access:empty() and prosody.hosts[uploader_host]) or access:contains(uploader) or access:contains(uploader_host)) then
@@ -84,6 +98,11 @@
 		return false, upload_errors.new("filesize");
 	end
 
+	local uploader_quota = get_daily_quota(uploader);
+	if uploader_quota + filesize > daily_quota then
+		return false, upload_errors.new("quota");
+	end
+
 	if not ( file_types:empty() or file_types:contains(filetype) or file_types:contains(filetype:gsub("/.*", "/*")) ) then
 		return false, upload_errors.new("filetype");
 	end