[ejabberd] [PATCH] mod_shared_roster: Teach remove_user_from_group() and add_user_to_group() about special users

martin.langhoff at gmail.com martin.langhoff at gmail.com
Fri Apr 17 22:42:03 MSD 2009


From: Martin Langhoff <martin at laptop.org>

With this patch, if the 'User' parameter is @all@, @online, @recent@ or
@nearby@, the add/removes change the group options to set/unset the
related modes.

This allows mod_ctlextra and other modules that tap call into these
functions to manipulate the mode of the SRG without explicit extensions.

---

Discussion points (not meant to be included in the commit msg)

This is coded and tested on top of 2.0.3, and applies cleanly to the tip
of 2.0.x .

This makes mod_ctrlextra able to control SRGs fully (sometihng I need for
the OLPC XS), and I suspect other modules (xmlrpc?) can take advantage of
this.

I am not aware of any security implications -- the onus is on the caller to
apply access control. If the user calling it has the rights to setup a SRG,
then they probably can do quite a bit of damage already.

One check that might be good to add is that the host is the local host.
It seems that this is as trivial as Host == LServer, but I am not completely
certain that Host is always local.

A trivial patch with the above check follows.

cheers,


martin 

---
 src/mod_shared_roster.erl |   87 +++++++++++++++++++++++++++++++++++----------
 1 files changed, 68 insertions(+), 19 deletions(-)

diff --git a/src/mod_shared_roster.erl b/src/mod_shared_roster.erl
index d1b169d..1eb8e9a 100644
--- a/src/mod_shared_roster.erl
+++ b/src/mod_shared_roster.erl
@@ -620,15 +620,46 @@ is_user_in_group({_U, S} = US, Group, Host) ->
 %% @spec (Host::string(), {User::string(), Server::string()}, Group::string()) -> {atomic, ok}
 add_user_to_group(Host, US, Group) ->
     {LUser, LServer} = US,
-    %% Push this new user to members of groups where this group is displayed
-    push_user_to_displayed(LUser, LServer, Group, both),
-    %% Push members of groups that are displayed to this group
-    push_displayed_to_user(LUser, LServer, Group, Host, both),
-    R = #sr_user{us = US, group_host = {Group, Host}},
-    F = fun() ->
-		mnesia:write(R)
-	end,
-    mnesia:transaction(F).
+    
+    case regexp:match(LUser, "^@.+@$") of
+	{match,_,_} ->
+	    GroupOpts = mod_shared_roster:get_group_opts(Host, Group),
+	    AllUsersOpt =
+		case LUser == "@all@" of
+		    true -> [{all_users, true}];
+		    false -> []
+		end,
+	    %% FIXME: this should be specified by the user
+	    RecentUsersOpt =
+		case LUser == "@recent@" of
+		    true -> [{recent_users_days, 7}];
+		    false -> []
+		end,
+	    OnlineUsersOpt =
+		case LUser == "@online@" of
+		    true -> [{online_users, true}];
+		    false -> []
+		end,
+	    NearbyUsersOpt =
+		case LUser == "@nearby@" of
+		    true -> [{nearby_users, true}];
+		    false -> []
+		end,
+            mod_shared_roster:set_group_opts(
+	      Host, Group,
+	      GroupOpts ++ AllUsersOpt
+	      ++ RecentUsersOpt ++ OnlineUsersOpt ++ NearbyUsersOpt);
+	nomatch ->
+	    %% Push this new user to members of groups where this group is displayed
+	    push_user_to_displayed(LUser, LServer, Group, both),
+	    %% Push members of groups that are displayed to this group
+	    push_displayed_to_user(LUser, LServer, Group, Host, both),
+	    R = #sr_user{us = US, group_host = {Group, Host}},
+	    F = fun() ->
+			mnesia:write(R)
+	        end,
+	    mnesia:transaction(F)
+    end.
 
 push_displayed_to_user(LUser, LServer, Group, Host, Subscription) ->
     GroupsOpts = groups_with_opts(LServer),
@@ -638,17 +669,35 @@ push_displayed_to_user(LUser, LServer, Group, Host, Subscription) ->
 
 remove_user_from_group(Host, US, Group) ->
     GroupHost = {Group, Host},
-    R = #sr_user{us = US, group_host = GroupHost},
-    F = fun() ->
-		mnesia:delete_object(R)
-	end,
-    Result = mnesia:transaction(F),
     {LUser, LServer} = US,
-    %% Push removal of the old user to members of groups where the group that this user was members was displayed
-    push_user_to_displayed(LUser, LServer, Group, remove),
-    %% Push removal of members of groups that where displayed to the group which this user has left
-    push_displayed_to_user(LUser, LServer, Group, Host, remove),
-    Result.
+
+    case regexp:match(LUser, "^@.+@$") of
+	{match,_,_} ->
+	    GroupOpts = mod_shared_roster:get_group_opts(Host, Group),
+	    case LUser of
+		"@all@" ->
+		    NewGroupOpts = lists:filter(fun(X) -> X/={all_users,true} end, GroupOpts);
+		"@recent@" ->
+		    NewGroupOpts = lists:filter(fun(X) -> X/={recent_users_days,7} end, GroupOpts);
+		"@online@" ->
+		    NewGroupOpts = lists:filter(fun(X) -> X/={online_users,true} end, GroupOpts);
+		"@nearby@" ->
+		    NewGroupOpts = lists:filter(fun(X) -> X/={nearby_users,true} end, GroupOpts)
+	    end,
+            mod_shared_roster:set_group_opts(Host, Group, NewGroupOpts);
+	nomatch ->
+	    R = #sr_user{us = US, group_host = GroupHost},
+	    F = fun() ->
+			mnesia:delete_object(R)
+		end,
+	    Result = mnesia:transaction(F),
+	    %% Push removal of the old user to members of groups where the group that this user was members was displayed
+	    push_user_to_displayed(LUser, LServer, Group, remove),
+	    %% Push removal of members of groups that where displayed to the group which this user has left
+	    push_displayed_to_user(LUser, LServer, Group, Host, remove),
+	    Result
+    end.
+
 
 push_members_to_user(LUser, LServer, Group, Host, Subscription) ->
     GroupsOpts = groups_with_opts(LServer),
-- 
1.5.6.6



More information about the ejabberd mailing list