Changeset

5104:27b45d2c19fe

Merge 0.9->trunk
author Matthew Wild <mwild1@gmail.com>
date Sun, 26 Aug 2012 19:58:59 +0100
parents 5103:5a1488369c35 (diff) 5089:a5b683909f79 (current diff)
children 5106:ab338242e0da
files
diffstat 11 files changed, 78 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- a/core/usermanager.lua	Sat Aug 11 06:14:12 2012 +0500
+++ b/core/usermanager.lua	Sun Aug 26 19:58:59 2012 +0100
@@ -90,14 +90,9 @@
 end
 
 function delete_user(username, host)
-	local user = hosts[host].sessions[username];
-	if user and user.sessions then
-		for jid, session in pairs(user.sessions) do
-			session:close{ condition = "not-authorized", text = "Account deleted" };
-		end
-	end
 	local ok, err = hosts[host].users.delete_user(username);
 	if not ok then return nil, err; end
+	prosody.events.fire_event("user-deleted", { username = username, host = host });
 	return storagemanager.get_driver(host):purge(username);
 end
 
--- a/plugins/mod_admin_adhoc.lua	Sat Aug 11 06:14:12 2012 +0500
+++ b/plugins/mod_admin_adhoc.lua	Sun Aug 26 19:58:59 2012 +0100
@@ -14,6 +14,7 @@
 local keys, values = iterators.keys, iterators.values;
 local usermanager_user_exists = require "core.usermanager".user_exists;
 local usermanager_create_user = require "core.usermanager".create_user;
+local usermanager_delete_user = require "core.usermanager".delete_user;
 local usermanager_get_password = require "core.usermanager".get_password;
 local usermanager_set_password = require "core.usermanager".set_password;
 local is_admin = require "core.usermanager".is_admin;
@@ -142,7 +143,7 @@
 		local succeeded = {};
 		for _, aJID in ipairs(fields.accountjids) do
 			local username, host, resource = jid.split(aJID);
-			if (host == data.to) and  usermanager_user_exists(username, host) and disconnect_user(aJID) and usermanager_create_user(username, nil, host) then
+			if (host == data.to) and  usermanager_user_exists(username, host) and usermanager_delete_user(username, host) then
 				module:log("debug", "User %s has been deleted", aJID);
 				succeeded[#succeeded+1] = aJID;
 			else
--- a/plugins/mod_c2s.lua	Sat Aug 11 06:14:12 2012 +0500
+++ b/plugins/mod_c2s.lua	Sun Aug 26 19:58:59 2012 +0100
@@ -169,6 +169,16 @@
 	end
 end
 
+module:hook_global("user-deleted", function(event)
+	local username, host = event.username, event.host;
+	local user = hosts[host].sessions[username];
+	if user and user.sessions then
+		for jid, session in pairs(user.sessions) do
+			session:close{ condition = "not-authorized", text = "Account deleted" };
+		end
+	end
+end, 200);
+
 --- Port listener
 function listener.onconnect(conn)
 	local session = sm_new_session(conn);
--- a/plugins/mod_http.lua	Sat Aug 11 06:14:12 2012 +0500
+++ b/plugins/mod_http.lua	Sun Aug 26 19:58:59 2012 +0100
@@ -11,6 +11,7 @@
 
 local moduleapi = require "core.moduleapi";
 local url_parse = require "socket.url".parse;
+local url_build = require "socket.url".build;
 
 local server = require "net.http.server";
 
@@ -30,6 +31,9 @@
 	if method:sub(1,1) == "/" then
 		return nil;
 	end
+	if app_path == "/" and path:sub(1,1) == "/" then
+		app_path = "";
+	end
 	return method:upper().." "..host..app_path..path;
 end
 
@@ -39,6 +43,8 @@
 		or default_app_path); -- Default
 end
 
+local ports_by_scheme = { http = 80, https = 443, };
+
 -- Helper to deduce a module's external URL
 function moduleapi.http_url(module, app_name, default_path)
 	app_name = app_name or (module.name:gsub("^http_", ""));
@@ -47,12 +53,15 @@
 	local http_services = services:get("https") or services:get("http") or {};
 	for interface, ports in pairs(http_services) do
 		for port, services in pairs(ports) do
-			local path = get_base_path(module, app_name, default_path or "/"..app_name);
-			port = tonumber(ext.port) or port or 80;
-			if port == 80 then port = ""; else port = ":"..port; end
-			return (ext.scheme or services[1].service.name).."://"
-				..(ext.host or module.host)..port
-				..normalize_path(ext.path or "/")..(path:sub(2));
+			local url = {
+				scheme = (ext.scheme or services[1].service.name);
+				host = (ext.host or module.host);
+				port = tonumber(ext.port) or port or 80;
+				path = normalize_path(ext.path or "/")..
+					(get_base_path(module, app_name, default_path or "/"..app_name):sub(2));
+			}
+			if ports_by_scheme[url.scheme] == url.port then url.port = nil end
+			return url_build(url);
 		end
 	end
 end
--- a/plugins/mod_register.lua	Sat Aug 11 06:14:12 2012 +0500
+++ b/plugins/mod_register.lua	Sun Aug 26 19:58:59 2012 +0100
@@ -95,40 +95,23 @@
 		session.send(reply);
 	else -- stanza.attr.type == "set"
 		if query.tags[1] and query.tags[1].name == "remove" then
-			-- TODO delete user auth data, send iq response, kick all user resources with a <not-authorized/>, delete all user data
 			local username, host = session.username, session.host;
+
+			local old_session_close = session.close;
+			session.close = function(session, ...)
+				session.send(st.reply(stanza));
+				return old_session_close(session, ...);
+			end
 			
 			local ok, err = usermanager_delete_user(username, host);
 			
 			if not ok then
 				module:log("debug", "Removing user account %s@%s failed: %s", username, host, err);
+				session.close = old_session_close;
 				session.send(st.error_reply(stanza, "cancel", "service-unavailable", err));
 				return true;
 			end
 			
-			session.send(st.reply(stanza));
-			local roster = session.roster;
-			for _, session in pairs(hosts[host].sessions[username].sessions) do -- disconnect all resources
-				session:close({condition = "not-authorized", text = "Account deleted"});
-			end
-			-- TODO datamanager should be able to delete all user data itself
-			datamanager.store(username, host, "vcard", nil);
-			datamanager.store(username, host, "private", nil);
-			datamanager.store(username, host, "account_details", nil);
-			datamanager.list_store(username, host, "offline", nil);
-			local bare = username.."@"..host;
-			for jid, item in pairs(roster) do
-				if jid and jid ~= "pending" then
-					if item.subscription == "both" or item.subscription == "from" or (roster.pending and roster.pending[jid]) then
-						module:send(st.presence({type="unsubscribed", from=bare, to=jid}));
-					end
-					if item.subscription == "both" or item.subscription == "to" or item.ask then
-						module:send(st.presence({type="unsubscribe", from=bare, to=jid}));
-					end
-				end
-			end
-			datamanager.store(username, host, "roster", nil);
-			datamanager.store(username, host, "privacy", nil);
 			module:log("info", "User removed their account: %s@%s", username, host);
 			module:fire_event("user-deregistered", { username = username, host = host, source = "mod_register", session = session });
 		else
--- a/plugins/mod_roster.lua	Sat Aug 11 06:14:12 2012 +0500
+++ b/plugins/mod_roster.lua	Sun Aug 26 19:58:59 2012 +0100
@@ -15,6 +15,7 @@
 local tonumber = tonumber;
 local pairs, ipairs = pairs, ipairs;
 
+local rm_load_roster = require "core.rostermanager".load_roster;
 local rm_remove_from_roster = require "core.rostermanager".remove_from_roster;
 local rm_add_to_roster = require "core.rostermanager".add_to_roster;
 local rm_roster_push = require "core.rostermanager".roster_push;
@@ -137,3 +138,20 @@
 	end
 	return true;
 end);
+
+module:hook_global("user-deleted", function(event)
+	local username, host = event.username, event.host;
+	if host ~= module.host then return end
+	local bare = username .. "@" .. host;
+	local roster = rm_load_roster(username, host);
+	for jid, item in pairs(roster) do
+		if jid and jid ~= "pending" then
+			if item.subscription == "both" or item.subscription == "from" or (roster.pending and roster.pending[jid]) then
+				module:send(st.presence({type="unsubscribed", from=bare, to=jid}));
+			end
+			if item.subscription == "both" or item.subscription == "to" or item.ask then
+				module:send(st.presence({type="unsubscribe", from=bare, to=jid}));
+			end
+		end
+	end
+end, 300);
--- a/prosodyctl	Sat Aug 11 06:14:12 2012 +0500
+++ b/prosodyctl	Sun Aug 26 19:58:59 2012 +0100
@@ -366,7 +366,7 @@
 		return 1;
 	end
 	
-	local ok, msg = prosodyctl.passwd { user = user, host = host };
+	local ok, msg = prosodyctl.deluser { user = user, host = host };
 	
 	if ok then return 0; end
 	
--- a/tools/xep227toprosody.lua	Sat Aug 11 06:14:12 2012 +0500
+++ b/tools/xep227toprosody.lua	Sun Aug 26 19:58:59 2012 +0100
@@ -64,11 +64,11 @@
 	-- fetch current roster-table for username@host if he already has one
 	local roster = dm.load(username, host, "roster") or {};
 	-- merge imported roster-items with loaded roster
-	for item_tag in roster_items:childtags() do
+	for item_tag in roster_items:childtags("item") do
 		-- jid for this roster-item
 		local item_jid = item_tag.attr.jid
 		-- validate item stanzas
-		if (item_tag.name == "item") and (item_jid ~= "") then
+		if (item_jid ~= "") then
 			-- prepare roster item
 			-- TODO: is the subscription attribute optional?
 			local item = {subscription = item_tag.attr.subscription, groups = {}};
@@ -77,9 +77,9 @@
 				item.name = item_tag.attr.name;
 			end
 			-- optional: iterate over group stanzas inside item stanza
-			for group_tag in item_tag:childtags() do
+			for group_tag in item_tag:childtags("group") do
 				local group_name = group_tag:get_text();
-				if (group_tag.name == "group") and (group_name ~= "") then
+				if (group_name ~= "") then
 					item.groups[group_name] = true;
 				else
 					print("[error] invalid group stanza: "..group_tag:pretty_print());
@@ -100,7 +100,7 @@
 
 function store_private(username, host, private_items)
 	local private = dm.load(username, host, "private") or {};
-	for ch in private_items:childtags() do
+	for _, ch in ipairs(private_items.tags) do
 		--print("private :"..ch:pretty_print());
 		private[ch.name..":"..ch.attr.xmlns] = st.preserialize(ch);
 		print("[success] private item: " ..username.."@"..host.." - "..ch.name);
@@ -112,7 +112,7 @@
 function store_offline_messages(username, host, offline_messages)
 	-- TODO: maybe use list_load(), append and list_store() instead
 	--       of constantly reopening the file with list_append()?
-	for ch in offline_messages:childtags() do
+	for ch in offline_messages:childtags("message", "jabber:client") do
 		--print("message :"..ch:pretty_print());
 		local ret, err = dm.list_append(username, host, "offline", st.preserialize(ch));
 		print("["..(err or "success").."] stored offline message: " ..username.."@"..host.." - "..ch.attr.from);
--- a/util/datamanager.lua	Sat Aug 11 06:14:12 2012 +0500
+++ b/util/datamanager.lua	Sun Aug 26 19:58:59 2012 +0100
@@ -309,18 +309,29 @@
 	return list;
 end
 
+local function do_remove(path)
+	local ok, err = os_remove(path);
+	if not ok and lfs.attributes(path, "mode") then
+		return ok, err;
+	end
+	return true
+end
+
 function purge(username, host)
 	local host_dir = format("%s/%s/", data_path, encode(host));
 	local deleted = 0;
+	local errs = {};
 	for file in lfs.dir(host_dir) do
 		if lfs.attributes(host_dir..file, "mode") == "directory" then
 			local store = decode(file);
-			deleted = deleted + (os_remove(getpath(username, host, store)) and 1 or 0);
-			deleted = deleted + (os_remove(getpath(username, host, store, "list")) and 1 or 0);
-			-- We this will generate loads of "No such file or directory", but do we care?
+			local ok, err = do_remove(getpath(username, host, store));
+			if not ok then errs[#errs+1] = err; end
+
+			local ok, err = do_remove(getpath(username, host, store, "list"));
+			if not ok then errs[#errs+1] = err; end
 		end
 	end
-	return deleted > 0, deleted;
+	return #errs == 0, t_concat(errs, ", ");
 end
 
 return _M;
--- a/util/prosodyctl.lua	Sat Aug 11 06:14:12 2012 +0500
+++ b/util/prosodyctl.lua	Sun Aug 26 19:58:59 2012 +0100
@@ -176,9 +176,9 @@
 	if not _M.user_exists(params) then
 		return false, "no-such-user";
 	end
-	params.password = nil;
+	local user, host = nodeprep(params.user), nameprep(params.host);
 	
-	return _M.adduser(params);
+	return usermanager.delete_user(user, host);
 end
 
 function getpid()
--- a/util/stanza.lua	Sat Aug 11 06:14:12 2012 +0500
+++ b/util/stanza.lua	Sun Aug 26 19:58:59 2012 +0100
@@ -237,7 +237,7 @@
 	end
 	type = error_tag.attr.type;
 	
-	for child in error_tag:childtags() do
+	for _, child in ipairs(error_tag.tags) do
 		if child.attr.xmlns == xmlns_stanzas then
 			if not text and child.name == "text" then
 				text = child:get_text();