mod_http_file_share: Add support for removing old files (default 2 weeks)
authorKim Alvefur <zash@zash.se>
Wed, 27 Jan 2021 22:09:26 +0100
changeset 11332 ceaa3cebf28b
parent 11331 6f2b69469060
child 11333 2a431d3ad8f1
mod_http_file_share: Add support for removing old files (default 2 weeks)
plugins/mod_http_file_share.lua
--- a/plugins/mod_http_file_share.lua	Wed Jan 27 19:51:36 2021 +0100
+++ b/plugins/mod_http_file_share.lua	Wed Jan 27 22:09:26 2021 +0100
@@ -32,6 +32,7 @@
 local external_base_url = module:get_option_string(module.name .. "_base_url");
 local file_size_limit = module:get_option_number(module.name .. "_size_limit", 10 * 1024 * 1024); -- 10 MB
 local file_types = module:get_option_set(module.name .. "_allowed_file_types", {});
+local expiry = module:get_option_number(module.name .. "_expires_after", 7 * 86400);
 
 local access = module:get_option_set(module.name .. "_access", {});
 
@@ -256,7 +257,64 @@
 	return response:send_file(handle);
 end
 
--- TODO periodic cleanup job
+if expiry >= 0 and not external_base_url then
+	-- TODO HTTP DELETE to the external endpoint?
+	local array = require "util.array";
+	local async = require "util.async";
+	local ENOENT = require "util.pposix".ENOENT;
+
+	local reaper_task = async.runner(function(boundary_time)
+		local iter, total = assert(uploads:find(nil, {["end"] = boundary_time; total = true}));
+
+		if total == 0 then
+			module:log("info", "No expired to prune");
+			return;
+		end
+
+		module:log("info", "Pruning expired files uploaded earlier than %s", dt.datetime(boundary_time));
+
+		local obsolete_files = array();
+		local i = 0;
+		for slot_id in iter do
+			i = i + 1;
+			obsolete_files:push(get_filename(slot_id));
+		end
+
+		local n = 0;
+		obsolete_files:filter(function(filename)
+			n = n + 1;
+			local deleted, err, errno = os.remove(filename);
+			if deleted or errno == ENOENT then
+				return false;
+			else
+				module:log("error", "Could not delete file %q: %s", filename, err);
+				return true;
+			end
+		end);
+
+		local deletion_query = {["end"] = boundary_time};
+		if #obsolete_files == 0 then
+			module:log("info", "All %d expired files deleted", n);
+		else
+			module:log("warn", "%d out of %d expired files could not be deleted", #obsolete_files, n);
+			deletion_query = {ids = obsolete_files};
+		end
+
+		local removed, err = uploads:delete(nil, deletion_query);
+
+		if removed == true or removed == n or removed == #obsolete_files then
+			module:log("debug", "Removed all metadata for expired uploaded files");
+		else
+			module:log("error", "Problem removing metadata for deleted files: %s", err);
+		end
+
+	end);
+
+	module:add_timer(1, function ()
+		reaper_task:run(os.time()-expiry);
+		return 60*60;
+	end);
+end
 
 module:hook("iq-get/host/urn:xmpp:http:upload:0:request", handle_slot_request);