Fix missing presences when adding shared groups (Github PR#99, thanks to Bokner)

This commit is contained in:
Badlop 2015-01-07 13:11:53 +01:00
parent 3882c4d514
commit b88fa6f617
1 changed files with 75 additions and 33 deletions

View File

@ -835,12 +835,13 @@ add_user_to_group(Host, US, Group) ->
(?MODULE):set_group_opts(Host, Group, (?MODULE):set_group_opts(Host, Group,
GroupOpts ++ MoreGroupOpts); GroupOpts ++ MoreGroupOpts);
nomatch -> nomatch ->
push_user_to_displayed(LUser, LServer, Group, Host, DisplayedToGroups = displayed_to_groups(Group, Host),
both), DisplayedGroups = get_displayed_groups(Group, LServer),
push_displayed_to_user(LUser, LServer, Group, Host, push_user_to_displayed(LUser, LServer, Group, Host, both, DisplayedToGroups),
both), push_displayed_to_user(LUser, LServer, Host, both, DisplayedGroups),
add_user_to_group(Host, US, Group, broadcast_user_to_displayed(LUser, LServer, Host, both, DisplayedToGroups),
gen_mod:db_type(Host, ?MODULE)) broadcast_displayed_to_user(LUser, LServer, Host, both, DisplayedGroups),
add_user_to_group(Host, US, Group, gen_mod:db_type(Host, ?MODULE))
end. end.
add_user_to_group(Host, US, Group, mnesia) -> add_user_to_group(Host, US, Group, mnesia) ->
@ -865,12 +866,17 @@ add_user_to_group(Host, US, Group, odbc) ->
end, end,
ejabberd_odbc:sql_transaction(Host, F). ejabberd_odbc:sql_transaction(Host, F).
push_displayed_to_user(LUser, LServer, Group, Host, get_displayed_groups(Group, LServer) ->
Subscription) ->
GroupsOpts = groups_with_opts(LServer), GroupsOpts = groups_with_opts(LServer),
GroupOpts = proplists:get_value(Group, GroupsOpts, []), GroupOpts = proplists:get_value(Group, GroupsOpts, []),
DisplayedGroups = proplists:get_value(displayed_groups, proplists:get_value(displayed_groups, GroupOpts, []).
GroupOpts, []),
broadcast_displayed_to_user(LUser, LServer, Host, Subscription, DisplayedGroups) ->
[broadcast_members_to_user(LUser, LServer, DGroup, Host,
Subscription)
|| DGroup <- DisplayedGroups].
push_displayed_to_user(LUser, LServer, Host, Subscription, DisplayedGroups) ->
[push_members_to_user(LUser, LServer, DGroup, Host, [push_members_to_user(LUser, LServer, DGroup, Host,
Subscription) Subscription)
|| DGroup <- DisplayedGroups]. || DGroup <- DisplayedGroups].
@ -894,10 +900,10 @@ remove_user_from_group(Host, US, Group) ->
nomatch -> nomatch ->
Result = remove_user_from_group(Host, US, Group, Result = remove_user_from_group(Host, US, Group,
gen_mod:db_type(Host, ?MODULE)), gen_mod:db_type(Host, ?MODULE)),
push_user_to_displayed(LUser, LServer, Group, Host, DisplayedToGroups = displayed_to_groups(Group, Host),
remove), DisplayedGroups = get_displayed_groups(Group, LServer),
push_displayed_to_user(LUser, LServer, Group, Host, push_user_to_displayed(LUser, LServer, Group, Host, remove, DisplayedToGroups),
remove), push_displayed_to_user(LUser, LServer, Host, remove, DisplayedGroups),
Result Result
end. end.
@ -930,10 +936,17 @@ push_members_to_user(LUser, LServer, Group, Host,
end, end,
Members). Members).
broadcast_members_to_user(LUser, LServer, Group, Host, Subscription) ->
Members = get_group_users(Host, Group),
lists:foreach(
fun({U, S}) ->
broadcast_subscription(U, S, {LUser, LServer, <<"">>}, Subscription)
end, Members).
register_user(User, Server) -> register_user(User, Server) ->
Groups = get_user_groups({User, Server}), Groups = get_user_groups({User, Server}),
[push_user_to_displayed(User, Server, Group, Server, [push_user_to_displayed(User, Server, Group, Server,
both) both, displayed_to_groups(Group, Server))
|| Group <- Groups]. || Group <- Groups].
remove_user(User, Server) -> remove_user(User, Server) ->
@ -965,17 +978,18 @@ push_user_to_members(User, Server, Subscription) ->
end, end,
lists:usort(SpecialGroups ++ UserGroups)). lists:usort(SpecialGroups ++ UserGroups)).
push_user_to_displayed(LUser, LServer, Group, Host, push_user_to_displayed(LUser, LServer, Group, Host, Subscription, DisplayedToGroupsOpts) ->
Subscription) ->
GroupsOpts = groups_with_opts(Host), GroupsOpts = groups_with_opts(Host),
GroupOpts = proplists:get_value(Group, GroupsOpts, []), GroupOpts = proplists:get_value(Group, GroupsOpts, []),
GroupName = proplists:get_value(name, GroupOpts, Group), GroupName = proplists:get_value(name, GroupOpts, Group),
DisplayedToGroupsOpts = displayed_to_groups(Group,
Host),
[push_user_to_group(LUser, LServer, GroupD, Host, [push_user_to_group(LUser, LServer, GroupD, Host,
GroupName, Subscription) GroupName, Subscription)
|| {GroupD, _Opts} <- DisplayedToGroupsOpts]. || {GroupD, _Opts} <- DisplayedToGroupsOpts].
broadcast_user_to_displayed(LUser, LServer, Host, Subscription, DisplayedToGroupsOpts) ->
[broadcast_user_to_group(LUser, LServer, GroupD, Host, Subscription)
|| {GroupD, _Opts} <- DisplayedToGroupsOpts].
push_user_to_group(LUser, LServer, Group, Host, push_user_to_group(LUser, LServer, Group, Host,
GroupName, Subscription) -> GroupName, Subscription) ->
lists:foreach(fun ({U, S}) lists:foreach(fun ({U, S})
@ -987,6 +1001,13 @@ push_user_to_group(LUser, LServer, Group, Host,
end, end,
get_group_users(Host, Group)). get_group_users(Host, Group)).
broadcast_user_to_group(LUser, LServer, Group, Host, Subscription) ->
lists:foreach(
fun({U, S}) when (U == LUser) and (S == LServer) -> ok;
({U, S}) ->
broadcast_subscription(LUser, LServer, {U, S, <<"">>}, Subscription)
end, get_group_users(Host, Group)).
%% Get list of groups to which this group is displayed %% Get list of groups to which this group is displayed
displayed_to_groups(GroupName, LServer) -> displayed_to_groups(GroupName, LServer) ->
GroupsOpts = groups_with_opts(LServer), GroupsOpts = groups_with_opts(LServer),
@ -997,11 +1018,7 @@ displayed_to_groups(GroupName, LServer) ->
end, end,
GroupsOpts). GroupsOpts).
push_item(User, Server, From, Item) -> push_item(User, Server, Item) ->
ejabberd_sm:route(From,
jlib:make_jid(User, Server, <<"">>),
{broadcast, {item, Item#roster.jid,
Item#roster.subscription}}),
Stanza = jlib:iq_to_xml(#iq{type = set, Stanza = jlib:iq_to_xml(#iq{type = set,
xmlns = ?NS_ROSTER, xmlns = ?NS_ROSTER,
id = <<"push", (randoms:get_string())/binary>>, id = <<"push", (randoms:get_string())/binary>>,
@ -1022,8 +1039,7 @@ push_roster_item(User, Server, ContactU, ContactS,
us = {User, Server}, jid = {ContactU, ContactS, <<"">>}, us = {User, Server}, jid = {ContactU, ContactS, <<"">>},
name = <<"">>, subscription = Subscription, ask = none, name = <<"">>, subscription = Subscription, ask = none,
groups = [GroupName]}, groups = [GroupName]},
push_item(User, Server, push_item(User, Server, Item).
jlib:make_jid(<<"">>, Server, <<"">>), Item).
item_to_xml(Item) -> item_to_xml(Item) ->
Attrs1 = [{<<"jid">>, Attrs1 = [{<<"jid">>,
@ -1067,14 +1083,16 @@ user_available(New) ->
case length(Resources) of case length(Resources) of
%% first session for this user %% first session for this user
1 -> 1 ->
OnlineGroups = get_special_users_groups_online(LServer), UserGroups = get_user_groups({LUser, LServer}),
lists:foreach(fun (OG) -> lists:foreach(fun (OG) ->
?DEBUG("user_available: pushing ~p @ ~p grp ~p", ?DEBUG("user_available: pushing ~p @ ~p grp ~p",
[LUser, LServer, OG]), [LUser, LServer, OG]),
push_user_to_displayed(LUser, LServer, OG, DisplayedToGroups = displayed_to_groups(OG, LServer),
LServer, both) DisplayedGroups = get_displayed_groups(OG, LServer),
broadcast_displayed_to_user(LUser, LServer, LServer, both, DisplayedGroups),
broadcast_user_to_displayed(LUser, LServer, LServer, both, DisplayedToGroups)
end, end,
OnlineGroups); UserGroups);
_ -> ok _ -> ok
end. end.
@ -1089,9 +1107,9 @@ unset_presence(LUser, LServer, Resource, Status) ->
OnlineGroups = get_special_users_groups_online(LServer), OnlineGroups = get_special_users_groups_online(LServer),
lists:foreach(fun (OG) -> lists:foreach(fun (OG) ->
push_user_to_displayed(LUser, LServer, OG, push_user_to_displayed(LUser, LServer, OG,
LServer, remove), LServer, remove, displayed_to_groups(OG, LServer)),
push_displayed_to_user(LUser, LServer, OG, push_displayed_to_user(LUser, LServer,
LServer, remove) LServer, remove, displayed_to_groups(OG, LServer))
end, end,
OnlineGroups); OnlineGroups);
_ -> ok _ -> ok
@ -1306,6 +1324,11 @@ shared_roster_group_parse_query(Host, Group, Query) ->
true -> [{online_users, true}]; true -> [{online_users, true}];
false -> [] false -> []
end, end,
CurrentDisplayedGroups = get_displayed_groups(Group, Host),
AddedDisplayedGroups = DispGroups -- CurrentDisplayedGroups,
RemovedDisplayedGroups = CurrentDisplayedGroups -- DispGroups,
displayed_groups_update(OldMembers, RemovedDisplayedGroups, remove),
displayed_groups_update(OldMembers, AddedDisplayedGroups, both),
(?MODULE):set_group_opts(Host, Group, (?MODULE):set_group_opts(Host, Group,
NameOpt ++ NameOpt ++
DispGroupsOpt ++ DispGroupsOpt ++
@ -1346,6 +1369,25 @@ split_grouphost(Host, Group) ->
[_] -> {Host, Group} [_] -> {Host, Group}
end. end.
broadcast_subscription(User, Server, ContactJid, Subscription) ->
ejabberd_sm:route(
jlib:make_jid(<<"">>, Server, <<"">>),
jlib:make_jid(User, Server, <<"">>),
{broadcast, {item, ContactJid,
Subscription}}).
displayed_groups_update(Members, DisplayedGroups, Subscription) ->
lists:foreach(fun({U, S}) ->
push_displayed_to_user(U, S, S, Subscription, DisplayedGroups),
case Subscription of
both ->
broadcast_displayed_to_user(U, S, S, to, DisplayedGroups),
broadcast_displayed_to_user(U, S, S, from, DisplayedGroups);
Subscr ->
broadcast_displayed_to_user(U, S, S, Subscr, DisplayedGroups)
end
end, Members).
make_jid_s(U, S) -> make_jid_s(U, S) ->
ejabberd_odbc:escape(jlib:jid_to_string(jlib:jid_tolower(jlib:make_jid(U, ejabberd_odbc:escape(jlib:jid_to_string(jlib:jid_tolower(jlib:make_jid(U,
S, S,