mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-28 16:34:13 +01:00
Allow to get subscriptions on a given node (EJAB-712), and presence based fixes
SVN Revision: 2066
This commit is contained in:
parent
18af5f8675
commit
90263cf0e7
@ -1,3 +1,11 @@
|
|||||||
|
2009-05-08 Christophe Romain <christophe.romain@process-one.net>
|
||||||
|
|
||||||
|
* src/mod_pubsub/mod_pubsub.erl: Allow to get subscriptions on a given
|
||||||
|
node (EJAB-712); Improve XML schema validation on publish item;
|
||||||
|
Remove subscriptions of users whose authorization has been removed on
|
||||||
|
nodes with presence access model; Do not allow unsubscribed user to
|
||||||
|
subscribe node with presence access model.
|
||||||
|
|
||||||
2009-05-08 Mickael Remond <mremond@process-one.net>
|
2009-05-08 Mickael Remond <mremond@process-one.net>
|
||||||
|
|
||||||
* src/ejabberd_app.erl: Better support for profiling.
|
* src/ejabberd_app.erl: Better support for profiling.
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
|
|
||||||
%% exports for hooks
|
%% exports for hooks
|
||||||
-export([presence_probe/3,
|
-export([presence_probe/3,
|
||||||
|
in_subscription/6,
|
||||||
out_subscription/4,
|
out_subscription/4,
|
||||||
remove_user/2,
|
remove_user/2,
|
||||||
disco_local_identity/5,
|
disco_local_identity/5,
|
||||||
@ -177,6 +178,7 @@ init([ServerHost, Opts]) ->
|
|||||||
ejabberd_hooks:add(disco_sm_features, ServerHost, ?MODULE, disco_sm_features, 75),
|
ejabberd_hooks:add(disco_sm_features, ServerHost, ?MODULE, disco_sm_features, 75),
|
||||||
ejabberd_hooks:add(disco_sm_items, ServerHost, ?MODULE, disco_sm_items, 75),
|
ejabberd_hooks:add(disco_sm_items, ServerHost, ?MODULE, disco_sm_items, 75),
|
||||||
ejabberd_hooks:add(presence_probe_hook, ServerHost, ?MODULE, presence_probe, 50),
|
ejabberd_hooks:add(presence_probe_hook, ServerHost, ?MODULE, presence_probe, 50),
|
||||||
|
ejabberd_hooks:add(roster_in_subscription, ServerHost, ?MODULE, in_subscription, 50),
|
||||||
ejabberd_hooks:add(roster_out_subscription, ServerHost, ?MODULE, out_subscription, 50),
|
ejabberd_hooks:add(roster_out_subscription, ServerHost, ?MODULE, out_subscription, 50),
|
||||||
ejabberd_hooks:add(remove_user, ServerHost, ?MODULE, remove_user, 50),
|
ejabberd_hooks:add(remove_user, ServerHost, ?MODULE, remove_user, 50),
|
||||||
ejabberd_hooks:add(anonymous_purge_hook, ServerHost, ?MODULE, remove_user, 50),
|
ejabberd_hooks:add(anonymous_purge_hook, ServerHost, ?MODULE, remove_user, 50),
|
||||||
@ -632,7 +634,13 @@ out_subscription(User, Server, JID, subscribed) ->
|
|||||||
end,
|
end,
|
||||||
Proc = gen_mod:get_module_proc(Server, ?PROCNAME),
|
Proc = gen_mod:get_module_proc(Server, ?PROCNAME),
|
||||||
gen_server:cast(Proc, {presence, PUser, PServer, PResources, Owner});
|
gen_server:cast(Proc, {presence, PUser, PServer, PResources, Owner});
|
||||||
out_subscription(_, _, _, _) ->
|
out_subscription(_,_,_,_) ->
|
||||||
|
ok.
|
||||||
|
in_subscription(_, User, Server, Subscriber, unsubscribed, _) ->
|
||||||
|
Owner = jlib:make_jid(User, Server, ""),
|
||||||
|
Proc = gen_mod:get_module_proc(Server, ?PROCNAME),
|
||||||
|
gen_server:cast(Proc, {unsubscribe, Subscriber, Owner});
|
||||||
|
in_subscription(_, _, _, _, _, _) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
%% -------
|
%% -------
|
||||||
@ -703,6 +711,33 @@ handle_cast({remove_user, LUser, LServer}, State) ->
|
|||||||
delete_node(Host, ["home", LServer, LUser], Owner),
|
delete_node(Host, ["home", LServer, LUser], Owner),
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
|
|
||||||
|
handle_cast({unsubscribe, Subscriber, Owner}, State) ->
|
||||||
|
Host = State#state.host,
|
||||||
|
BJID = jlib:jid_tolower(jlib:jid_remove_resource(Owner)),
|
||||||
|
lists:foreach(fun(PType) ->
|
||||||
|
{result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Subscriber]),
|
||||||
|
lists:foreach(fun
|
||||||
|
({Node, subscribed, JID}) ->
|
||||||
|
Action = fun(#pubsub_node{options = Options, owners = Owners, type = Type, id = NodeId}) ->
|
||||||
|
case get_option(Options, access_model) of
|
||||||
|
presence ->
|
||||||
|
case lists:member(BJID, Owners) of
|
||||||
|
true ->
|
||||||
|
node_call(Type, unsubscribe_node, [NodeId, Subscriber, JID, all]);
|
||||||
|
false ->
|
||||||
|
ok
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
ok
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
transaction(Host, Node, Action, sync_dirty);
|
||||||
|
(_) ->
|
||||||
|
ok
|
||||||
|
end, Subscriptions)
|
||||||
|
end, State#state.plugins),
|
||||||
|
{noreply, State};
|
||||||
|
|
||||||
handle_cast(_Msg, State) ->
|
handle_cast(_Msg, State) ->
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
|
|
||||||
@ -753,6 +788,7 @@ terminate(_Reason, #state{host = Host,
|
|||||||
ejabberd_hooks:delete(disco_sm_features, ServerHost, ?MODULE, disco_sm_features, 75),
|
ejabberd_hooks:delete(disco_sm_features, ServerHost, ?MODULE, disco_sm_features, 75),
|
||||||
ejabberd_hooks:delete(disco_sm_items, ServerHost, ?MODULE, disco_sm_items, 75),
|
ejabberd_hooks:delete(disco_sm_items, ServerHost, ?MODULE, disco_sm_items, 75),
|
||||||
ejabberd_hooks:delete(presence_probe_hook, ServerHost, ?MODULE, presence_probe, 50),
|
ejabberd_hooks:delete(presence_probe_hook, ServerHost, ?MODULE, presence_probe, 50),
|
||||||
|
ejabberd_hooks:delete(roster_in_subscription, ServerHost, ?MODULE, in_subscription, 50),
|
||||||
ejabberd_hooks:delete(roster_out_subscription, ServerHost, ?MODULE, out_subscription, 50),
|
ejabberd_hooks:delete(roster_out_subscription, ServerHost, ?MODULE, out_subscription, 50),
|
||||||
ejabberd_hooks:delete(remove_user, ServerHost, ?MODULE, remove_user, 50),
|
ejabberd_hooks:delete(remove_user, ServerHost, ?MODULE, remove_user, 50),
|
||||||
ejabberd_hooks:delete(anonymous_purge_hook, ServerHost, ?MODULE, remove_user, 50),
|
ejabberd_hooks:delete(anonymous_purge_hook, ServerHost, ?MODULE, remove_user, 50),
|
||||||
@ -1121,7 +1157,7 @@ iq_pubsub(Host, ServerHost, From, IQType, SubEl, _Lang, Access, Plugins) ->
|
|||||||
end, [], xml:remove_cdata(Els)),
|
end, [], xml:remove_cdata(Els)),
|
||||||
get_items(Host, Node, From, SubId, MaxItems, ItemIDs);
|
get_items(Host, Node, From, SubId, MaxItems, ItemIDs);
|
||||||
{get, "subscriptions"} ->
|
{get, "subscriptions"} ->
|
||||||
get_subscriptions(Host, From, Plugins);
|
get_subscriptions(Host, Node, From, Plugins);
|
||||||
{get, "affiliations"} ->
|
{get, "affiliations"} ->
|
||||||
get_affiliations(Host, From, Plugins);
|
get_affiliations(Host, From, Plugins);
|
||||||
{get, "options"} ->
|
{get, "options"} ->
|
||||||
@ -1542,7 +1578,7 @@ subscribe_node(Host, Node, From, JID) ->
|
|||||||
J -> jlib:jid_tolower(J)
|
J -> jlib:jid_tolower(J)
|
||||||
end,
|
end,
|
||||||
SubId = uniqid(),
|
SubId = uniqid(),
|
||||||
Action = fun(#pubsub_node{options = Options, type = Type, id = NodeId}) ->
|
Action = fun(#pubsub_node{options = Options, owners = [Owner|_], type = Type, id = NodeId}) ->
|
||||||
Features = features(Type),
|
Features = features(Type),
|
||||||
SubscribeFeature = lists:member("subscribe", Features),
|
SubscribeFeature = lists:member("subscribe", Features),
|
||||||
SubscribeConfig = get_option(Options, subscribe),
|
SubscribeConfig = get_option(Options, subscribe),
|
||||||
@ -1556,9 +1592,12 @@ subscribe_node(Host, Node, From, JID) ->
|
|||||||
Subscriber, AllowedGroups);
|
Subscriber, AllowedGroups);
|
||||||
_ ->
|
_ ->
|
||||||
case Subscriber of
|
case Subscriber of
|
||||||
{"", "", ""} -> {false, false};
|
{"", "", ""} ->
|
||||||
{U, S, _} -> get_roster_info(U, S, Subscriber,
|
{false, false};
|
||||||
AllowedGroups)
|
_ ->
|
||||||
|
{OU, OS, _} = Owner,
|
||||||
|
get_roster_info(OU, OS,
|
||||||
|
Subscriber, AllowedGroups)
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
if
|
if
|
||||||
@ -1685,10 +1724,10 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) ->
|
|||||||
PayloadSize > PayloadMaxSize ->
|
PayloadSize > PayloadMaxSize ->
|
||||||
%% Entity attempts to publish very large payload
|
%% Entity attempts to publish very large payload
|
||||||
{error, extended_error(?ERR_NOT_ACCEPTABLE, "payload-too-big")};
|
{error, extended_error(?ERR_NOT_ACCEPTABLE, "payload-too-big")};
|
||||||
PayloadCount == 0 ->
|
(PayloadCount == 0) and (Payload == []) ->
|
||||||
%% Publisher attempts to publish to payload node with no payload
|
%% Publisher attempts to publish to payload node with no payload
|
||||||
{error, extended_error(?ERR_BAD_REQUEST, "payload-required")};
|
{error, extended_error(?ERR_BAD_REQUEST, "payload-required")};
|
||||||
PayloadCount > 1 ->
|
(PayloadCount > 1) or (PayloadCount == 0) ->
|
||||||
%% Entity attempts to publish item with multiple payload elements
|
%% Entity attempts to publish item with multiple payload elements
|
||||||
{error, extended_error(?ERR_BAD_REQUEST, "invalid-payload")};
|
{error, extended_error(?ERR_BAD_REQUEST, "invalid-payload")};
|
||||||
(DeliverPayloads == 0) and (PersistItems == 0) and (PayloadSize > 0) ->
|
(DeliverPayloads == 0) and (PersistItems == 0) and (PayloadSize > 0) ->
|
||||||
@ -2009,12 +2048,12 @@ get_affiliations(Host, Node, JID) ->
|
|||||||
Action = fun(#pubsub_node{type = Type, id = NodeId}) ->
|
Action = fun(#pubsub_node{type = Type, id = NodeId}) ->
|
||||||
Features = features(Type),
|
Features = features(Type),
|
||||||
RetrieveFeature = lists:member("modify-affiliations", Features),
|
RetrieveFeature = lists:member("modify-affiliations", Features),
|
||||||
Affiliation = node_call(Type, get_affiliation, [NodeId, JID]),
|
{result, Affiliation} = node_call(Type, get_affiliation, [NodeId, JID]),
|
||||||
if
|
if
|
||||||
not RetrieveFeature ->
|
not RetrieveFeature ->
|
||||||
%% Service does not support modify affiliations
|
%% Service does not support modify affiliations
|
||||||
{error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, "modify-affiliations")};
|
{error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, "modify-affiliations")};
|
||||||
Affiliation /= {result, owner} ->
|
Affiliation /= owner ->
|
||||||
%% Entity is not an owner
|
%% Entity is not an owner
|
||||||
{error, ?ERR_FORBIDDEN};
|
{error, ?ERR_FORBIDDEN};
|
||||||
true ->
|
true ->
|
||||||
@ -2105,14 +2144,15 @@ set_affiliations(Host, Node, From, EntitiesEls) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
%% @spec (Host, JID, Plugins) -> {error, Reason} | {result, Response}
|
%% @spec (Host, Node, JID, Plugins) -> {error, Reason} | {result, Response}
|
||||||
%% Host = host()
|
%% Host = host()
|
||||||
|
%% Node = pubsubNode()
|
||||||
%% JID = jid()
|
%% JID = jid()
|
||||||
%% Plugins = [Plugin::string()]
|
%% Plugins = [Plugin::string()]
|
||||||
%% Reason = stanzaError()
|
%% Reason = stanzaError()
|
||||||
%% Response = [pubsubIQResponse()]
|
%% Response = [pubsubIQResponse()]
|
||||||
%% @doc <p>Return the list of subscriptions as an XMPP response.</p>
|
%% @doc <p>Return the list of subscriptions as an XMPP response.</p>
|
||||||
get_subscriptions(Host, JID, Plugins) when is_list(Plugins) ->
|
get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) ->
|
||||||
Result = lists:foldl(
|
Result = lists:foldl(
|
||||||
fun(Type, {Status, Acc}) ->
|
fun(Type, {Status, Acc}) ->
|
||||||
Features = features(Type),
|
Features = features(Type),
|
||||||
@ -2130,36 +2170,57 @@ get_subscriptions(Host, JID, Plugins) when is_list(Plugins) ->
|
|||||||
case Result of
|
case Result of
|
||||||
{ok, Subscriptions} ->
|
{ok, Subscriptions} ->
|
||||||
Entities = lists:flatmap(
|
Entities = lists:flatmap(
|
||||||
fun({_, none}) -> [];
|
fun({_, none}) ->
|
||||||
({Node, Subscription}) ->
|
[];
|
||||||
|
({SubsNode, Subscription}) ->
|
||||||
|
case Node of
|
||||||
|
[] ->
|
||||||
[{xmlelement, "subscription",
|
[{xmlelement, "subscription",
|
||||||
[{"node", node_to_string(Node)},
|
[{"node", node_to_string(SubsNode)},
|
||||||
{"subscription", subscription_to_string(Subscription)}],
|
{"subscription", subscription_to_string(Subscription)}],
|
||||||
[]}];
|
[]}];
|
||||||
({_, none, _}) -> [];
|
SubsNode ->
|
||||||
({Node, Subscription, SubJID}) ->
|
|
||||||
[{xmlelement, "subscription",
|
[{xmlelement, "subscription",
|
||||||
[{"node", node_to_string(Node)},
|
[{"subscription", subscription_to_string(Subscription)}],
|
||||||
|
[]}];
|
||||||
|
_ ->
|
||||||
|
[]
|
||||||
|
end;
|
||||||
|
({_, none, _}) ->
|
||||||
|
[];
|
||||||
|
({SubsNode, Subscription, SubJID}) ->
|
||||||
|
case Node of
|
||||||
|
[] ->
|
||||||
|
[{xmlelement, "subscription",
|
||||||
|
[{"node", node_to_string(SubsNode)},
|
||||||
{"jid", jlib:jid_to_string(SubJID)},
|
{"jid", jlib:jid_to_string(SubJID)},
|
||||||
{"subscription", subscription_to_string(Subscription)}],
|
{"subscription", subscription_to_string(Subscription)}],
|
||||||
[]}]
|
[]}];
|
||||||
|
SubsNode ->
|
||||||
|
[{xmlelement, "subscription",
|
||||||
|
[{"jid", jlib:jid_to_string(SubJID)},
|
||||||
|
{"subscription", subscription_to_string(Subscription)}],
|
||||||
|
[]}];
|
||||||
|
_ ->
|
||||||
|
[]
|
||||||
|
end
|
||||||
end, lists:usort(lists:flatten(Subscriptions))),
|
end, lists:usort(lists:flatten(Subscriptions))),
|
||||||
{result, [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}],
|
{result, [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}],
|
||||||
[{xmlelement, "subscriptions", [],
|
[{xmlelement, "subscriptions", [],
|
||||||
Entities}]}]};
|
Entities}]}]};
|
||||||
{Error, _} ->
|
{Error, _} ->
|
||||||
Error
|
Error
|
||||||
end;
|
end.
|
||||||
get_subscriptions(Host, Node, JID) ->
|
get_subscriptions(Host, Node, JID) ->
|
||||||
Action = fun(#pubsub_node{type = Type, id = NodeId}) ->
|
Action = fun(#pubsub_node{type = Type, id = NodeId}) ->
|
||||||
Features = features(Type),
|
Features = features(Type),
|
||||||
RetrieveFeature = lists:member("manage-subscriptions", Features),
|
RetrieveFeature = lists:member("manage-subscriptions", Features),
|
||||||
Affiliation = node_call(Type, get_affiliation, [NodeId, JID]),
|
{result, Affiliation} = node_call(Type, get_affiliation, [NodeId, JID]),
|
||||||
if
|
if
|
||||||
not RetrieveFeature ->
|
not RetrieveFeature ->
|
||||||
%% Service does not support manage subscriptions
|
%% Service does not support manage subscriptions
|
||||||
{error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, "manage-subscriptions")};
|
{error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, "manage-subscriptions")};
|
||||||
Affiliation /= {result, owner} ->
|
Affiliation /= owner ->
|
||||||
%% Entity is not an owner
|
%% Entity is not an owner
|
||||||
{error, ?ERR_FORBIDDEN};
|
{error, ?ERR_FORBIDDEN};
|
||||||
true ->
|
true ->
|
||||||
|
Loading…
Reference in New Issue
Block a user