mirror of
https://github.com/processone/ejabberd.git
synced 2024-12-22 17:28:25 +01:00
Implement pubsub#get-pending Ad Hoc Command (EJAB-955) (thanks to Brian Cully)
SVN Revision: 2372
This commit is contained in:
parent
480c98e991
commit
360b4916b1
@ -54,6 +54,7 @@
|
|||||||
-define(NS_PUBSUB_NODE_CONFIG, "http://jabber.org/protocol/pubsub#node_config").
|
-define(NS_PUBSUB_NODE_CONFIG, "http://jabber.org/protocol/pubsub#node_config").
|
||||||
-define(NS_PUBSUB_SUB_OPTIONS, "http://jabber.org/protocol/pubsub#subscribe_options").
|
-define(NS_PUBSUB_SUB_OPTIONS, "http://jabber.org/protocol/pubsub#subscribe_options").
|
||||||
-define(NS_PUBSUB_SUB_AUTH, "http://jabber.org/protocol/pubsub#subscribe_authorization").
|
-define(NS_PUBSUB_SUB_AUTH, "http://jabber.org/protocol/pubsub#subscribe_authorization").
|
||||||
|
-define(NS_PUBSUB_GET_PENDING, "http://jabber.org/protocol/pubsub#get-pending").
|
||||||
-define(NS_COMMANDS, "http://jabber.org/protocol/commands").
|
-define(NS_COMMANDS, "http://jabber.org/protocol/commands").
|
||||||
-define(NS_BYTESTREAMS, "http://jabber.org/protocol/bytestreams").
|
-define(NS_BYTESTREAMS, "http://jabber.org/protocol/bytestreams").
|
||||||
-define(NS_ADMIN, "http://jabber.org/protocol/admin").
|
-define(NS_ADMIN, "http://jabber.org/protocol/admin").
|
||||||
|
@ -59,6 +59,7 @@ behaviour_info(callbacks) ->
|
|||||||
{get_entity_subscriptions, 2},
|
{get_entity_subscriptions, 2},
|
||||||
{get_subscriptions, 2},
|
{get_subscriptions, 2},
|
||||||
{set_subscriptions, 4},
|
{set_subscriptions, 4},
|
||||||
|
{get_pending_nodes, 2},
|
||||||
{get_states, 1},
|
{get_states, 1},
|
||||||
{get_state, 2},
|
{get_state, 2},
|
||||||
{set_state, 1},
|
{set_state, 1},
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
|
-include("adhoc.hrl").
|
||||||
-include("jlib.hrl").
|
-include("jlib.hrl").
|
||||||
-include("pubsub.hrl").
|
-include("pubsub.hrl").
|
||||||
|
|
||||||
@ -945,6 +946,15 @@ do_route(ServerHost, Access, Plugins, Host, From, To, Packet) ->
|
|||||||
sub_el = [{xmlelement, "vCard", [{"xmlns", XMLNS}],
|
sub_el = [{xmlelement, "vCard", [{"xmlns", XMLNS}],
|
||||||
iq_get_vcard(Lang)}]},
|
iq_get_vcard(Lang)}]},
|
||||||
ejabberd_router:route(To, From, jlib:iq_to_xml(Res));
|
ejabberd_router:route(To, From, jlib:iq_to_xml(Res));
|
||||||
|
#iq{type = set, xmlns = ?NS_COMMANDS} = IQ ->
|
||||||
|
Res = case iq_command(Host, ServerHost, From, IQ, Access, Plugins) of
|
||||||
|
{error, Error} ->
|
||||||
|
jlib:make_error_reply(Packet, Error);
|
||||||
|
{result, IQRes} ->
|
||||||
|
jlib:iq_to_xml(IQ#iq{type = result,
|
||||||
|
sub_el = IQRes})
|
||||||
|
end,
|
||||||
|
ejabberd_router:route(To, From, Res);
|
||||||
#iq{} ->
|
#iq{} ->
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet,
|
Packet,
|
||||||
@ -1282,6 +1292,140 @@ iq_pubsub_owner(Host, ServerHost, From, IQType, SubEl, Lang) ->
|
|||||||
{error, ?ERR_BAD_REQUEST}
|
{error, ?ERR_BAD_REQUEST}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
iq_command(Host, ServerHost, From, IQ, Access, Plugins) ->
|
||||||
|
case adhoc:parse_request(IQ) of
|
||||||
|
Req when is_record(Req, adhoc_request) ->
|
||||||
|
case adhoc_request(Host, ServerHost, From, Req, Access, Plugins) of
|
||||||
|
Resp when is_record(Resp, adhoc_response) ->
|
||||||
|
{result, [adhoc:produce_response(Req, Resp)]};
|
||||||
|
Error ->
|
||||||
|
Error
|
||||||
|
end;
|
||||||
|
Err ->
|
||||||
|
Err
|
||||||
|
end.
|
||||||
|
|
||||||
|
%% @doc <p>Processes an Ad Hoc Command.</p>
|
||||||
|
adhoc_request(Host, _ServerHost, Owner,
|
||||||
|
#adhoc_request{node = ?NS_PUBSUB_GET_PENDING,
|
||||||
|
lang = Lang,
|
||||||
|
action = "execute",
|
||||||
|
xdata = false},
|
||||||
|
_Access, Plugins) ->
|
||||||
|
send_pending_node_form(Host, Owner, Lang, Plugins);
|
||||||
|
adhoc_request(Host, _ServerHost, Owner,
|
||||||
|
#adhoc_request{node = ?NS_PUBSUB_GET_PENDING,
|
||||||
|
action = "execute",
|
||||||
|
xdata = XData},
|
||||||
|
_Access, _Plugins) ->
|
||||||
|
ParseOptions = case XData of
|
||||||
|
{xmlelement, "x", _Attrs, _SubEls} = XEl ->
|
||||||
|
case jlib:parse_xdata_submit(XEl) of
|
||||||
|
invalid ->
|
||||||
|
{error, ?ERR_BAD_REQUEST};
|
||||||
|
XData2 ->
|
||||||
|
case set_xoption(XData2, []) of
|
||||||
|
NewOpts when is_list(NewOpts) ->
|
||||||
|
{result, NewOpts};
|
||||||
|
Err ->
|
||||||
|
Err
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
?INFO_MSG("Bad XForm: ~p", [XData]),
|
||||||
|
{error, ?ERR_BAD_REQUEST}
|
||||||
|
end,
|
||||||
|
case ParseOptions of
|
||||||
|
{result, XForm} ->
|
||||||
|
case lists:keysearch(node, 1, XForm) of
|
||||||
|
{value, {_, Node}} ->
|
||||||
|
send_pending_auth_events(Host, Node, Owner);
|
||||||
|
false ->
|
||||||
|
{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "bad-payload")}
|
||||||
|
end;
|
||||||
|
Error ->
|
||||||
|
Error
|
||||||
|
end;
|
||||||
|
adhoc_request(_Host, _ServerHost, _Owner, Other, _Access, _Plugins) ->
|
||||||
|
?DEBUG("Couldn't process ad hoc command:~n~p", [Other]),
|
||||||
|
{error, ?ERR_ITEM_NOT_FOUND}.
|
||||||
|
|
||||||
|
%% @spec (Host, Owner) -> iqRes()
|
||||||
|
%% @doc <p>Sends the process pending subscriptions XForm for Host to
|
||||||
|
%% Owner.</p>
|
||||||
|
send_pending_node_form(Host, Owner, _Lang, Plugins) ->
|
||||||
|
Filter =
|
||||||
|
fun (Plugin) ->
|
||||||
|
lists:member("get-pending", features(Plugin))
|
||||||
|
end,
|
||||||
|
case lists:filter(Filter, Plugins) of
|
||||||
|
[] ->
|
||||||
|
{error, ?ERR_FEATURE_NOT_IMPLEMENTED};
|
||||||
|
Ps ->
|
||||||
|
XOpts = lists:map(fun (Node) ->
|
||||||
|
{xmlelement, "option", [],
|
||||||
|
[{xmlelement, "value", [],
|
||||||
|
[{xmlcdata, node_to_string(Node)}]}]}
|
||||||
|
end, get_pending_nodes(Host, Owner, Ps)),
|
||||||
|
XForm = {xmlelement, "x", [{"xmlns", ?NS_XDATA}, {"type", "form"}],
|
||||||
|
[{xmlelement, "field",
|
||||||
|
[{"type", "list-single"}, {"var", "pubsub#node"}],
|
||||||
|
lists:usort(XOpts)}]},
|
||||||
|
#adhoc_response{status = executing,
|
||||||
|
defaultaction = "execute",
|
||||||
|
elements = [XForm]}
|
||||||
|
end.
|
||||||
|
|
||||||
|
get_pending_nodes(Host, Owner, Plugins) ->
|
||||||
|
Tr =
|
||||||
|
fun (Type) ->
|
||||||
|
case node_call(Type, get_pending_nodes, [Host, Owner]) of
|
||||||
|
{result, Nodes} -> Nodes;
|
||||||
|
_ -> []
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
case transaction(fun () -> {result, lists:flatmap(Tr, Plugins)} end,
|
||||||
|
sync_dirty) of
|
||||||
|
{result, Res} -> Res;
|
||||||
|
Err -> Err
|
||||||
|
end.
|
||||||
|
|
||||||
|
%% @spec (Host, Node, Owner) -> iqRes()
|
||||||
|
%% @doc <p>Send a subscription approval form to Owner for all pending
|
||||||
|
%% subscriptions on Host and Node.</p>
|
||||||
|
send_pending_auth_events(Host, Node, Owner) ->
|
||||||
|
?DEBUG("Sending pending auth events for ~s on ~s:~s",
|
||||||
|
[jlib:jid_to_string(Owner), Host, node_to_string(Node)]),
|
||||||
|
Action =
|
||||||
|
fun (#pubsub_node{id = NodeID, type = Type} = N) ->
|
||||||
|
case lists:member("get-pending", features(Type)) of
|
||||||
|
true ->
|
||||||
|
case node_call(Type, get_affiliation, [NodeID, Owner]) of
|
||||||
|
{result, owner} ->
|
||||||
|
broadcast_pending_auth_events(N),
|
||||||
|
{result, ok};
|
||||||
|
_ ->
|
||||||
|
{error, ?ERR_FORBIDDEN}
|
||||||
|
end;
|
||||||
|
false ->
|
||||||
|
{error, ?ERR_FEATURE_NOT_IMPLEMENTED}
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
case transaction(Host, Node, Action, sync_dirty) of
|
||||||
|
{result, _} ->
|
||||||
|
#adhoc_response{};
|
||||||
|
Err ->
|
||||||
|
Err
|
||||||
|
end.
|
||||||
|
|
||||||
|
broadcast_pending_auth_events(#pubsub_node{type = Type, id = NodeID} = Node) ->
|
||||||
|
{result, Subscriptions} = node_call(Type, get_node_subscriptions, [NodeID]),
|
||||||
|
lists:foreach(fun ({J, pending, _SubID}) ->
|
||||||
|
send_authorization_request(Node, jlib:make_jid(J));
|
||||||
|
({J, pending}) ->
|
||||||
|
send_authorization_request(Node, jlib:make_jid(J))
|
||||||
|
end, Subscriptions).
|
||||||
|
|
||||||
%%% authorization handling
|
%%% authorization handling
|
||||||
|
|
||||||
send_authorization_request(#pubsub_node{owners = Owners, nodeid = {Host, Node}}, Subscriber) ->
|
send_authorization_request(#pubsub_node{owners = Owners, nodeid = {Host, Node}}, Subscriber) ->
|
||||||
@ -2412,19 +2556,19 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) ->
|
|||||||
end;
|
end;
|
||||||
({_, none, _}) ->
|
({_, none, _}) ->
|
||||||
[];
|
[];
|
||||||
({#pubsub_node{nodeid = {_, SubsNode}}, subscribed, SubID, SubJID}) ->
|
({#pubsub_node{nodeid = {_, SubsNode}}, Subscription, SubID, SubJID}) ->
|
||||||
case Node of
|
case Node of
|
||||||
[] ->
|
[] ->
|
||||||
[{xmlelement, "subscription",
|
[{xmlelement, "subscription",
|
||||||
[{"jid", jlib:jid_to_string(SubJID)},
|
[{"jid", jlib:jid_to_string(SubJID)},
|
||||||
{"subid", SubID},
|
{"subid", SubID},
|
||||||
{"subscription", subscription_to_string(subscribed)}|nodeAttr(SubsNode)],
|
{"subscription", subscription_to_string(Subscription)}|nodeAttr(SubsNode)],
|
||||||
[]}];
|
[]}];
|
||||||
SubsNode ->
|
SubsNode ->
|
||||||
[{xmlelement, "subscription",
|
[{xmlelement, "subscription",
|
||||||
[{"jid", jlib:jid_to_string(SubJID)},
|
[{"jid", jlib:jid_to_string(SubJID)},
|
||||||
{"subid", SubID},
|
{"subid", SubID},
|
||||||
{"subscription", subscription_to_string(subscribed)}],
|
{"subscription", subscription_to_string(Subscription)}],
|
||||||
[]}];
|
[]}];
|
||||||
_ ->
|
_ ->
|
||||||
[]
|
[]
|
||||||
@ -2468,11 +2612,10 @@ get_subscriptions(Host, Node, JID) ->
|
|||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
case transaction(Host, Node, Action, sync_dirty) of
|
case transaction(Host, Node, Action, sync_dirty) of
|
||||||
{result, {_, []}} ->
|
|
||||||
{error, ?ERR_ITEM_NOT_FOUND};
|
|
||||||
{result, {_, Subscriptions}} ->
|
{result, {_, Subscriptions}} ->
|
||||||
Entities = lists:flatmap(
|
Entities = lists:flatmap(
|
||||||
fun({_, none}) -> [];
|
fun({_, none}) -> [];
|
||||||
|
({_, pending, _}) -> [];
|
||||||
({AJID, Subscription}) ->
|
({AJID, Subscription}) ->
|
||||||
[{xmlelement, "subscription",
|
[{xmlelement, "subscription",
|
||||||
[{"jid", jlib:jid_to_string(AJID)},
|
[{"jid", jlib:jid_to_string(AJID)},
|
||||||
@ -3238,6 +3381,9 @@ set_xoption([{"pubsub#body_xslt", Value} | Opts], NewOpts) ->
|
|||||||
set_xoption([{"pubsub#collection", Value} | Opts], NewOpts) ->
|
set_xoption([{"pubsub#collection", Value} | Opts], NewOpts) ->
|
||||||
NewValue = [string_to_node(V) || V <- Value],
|
NewValue = [string_to_node(V) || V <- Value],
|
||||||
?SET_LIST_XOPT(collection, NewValue);
|
?SET_LIST_XOPT(collection, NewValue);
|
||||||
|
set_xoption([{"pubsub#node", [Value]} | Opts], NewOpts) ->
|
||||||
|
NewValue = string_to_node(Value),
|
||||||
|
?SET_LIST_XOPT(node, NewValue);
|
||||||
set_xoption([_ | Opts], NewOpts) ->
|
set_xoption([_ | Opts], NewOpts) ->
|
||||||
% skip unknown field
|
% skip unknown field
|
||||||
set_xoption(Opts, NewOpts).
|
set_xoption(Opts, NewOpts).
|
||||||
@ -3319,7 +3465,7 @@ features() ->
|
|||||||
% see plugin "delete-items", % RECOMMENDED
|
% see plugin "delete-items", % RECOMMENDED
|
||||||
% see plugin "delete-nodes", % RECOMMENDED
|
% see plugin "delete-nodes", % RECOMMENDED
|
||||||
% see plugin "filtered-notifications", % RECOMMENDED
|
% see plugin "filtered-notifications", % RECOMMENDED
|
||||||
%TODO "get-pending", % OPTIONAL
|
% see plugin "get-pending", % OPTIONAL
|
||||||
% see plugin "instant-nodes", % RECOMMENDED
|
% see plugin "instant-nodes", % RECOMMENDED
|
||||||
"item-ids", % RECOMMENDED
|
"item-ids", % RECOMMENDED
|
||||||
"last-published", % RECOMMENDED
|
"last-published", % RECOMMENDED
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
get_node_subscriptions/1,
|
get_node_subscriptions/1,
|
||||||
get_subscriptions/2,
|
get_subscriptions/2,
|
||||||
set_subscriptions/4,
|
set_subscriptions/4,
|
||||||
|
get_pending_nodes/2,
|
||||||
get_states/1,
|
get_states/1,
|
||||||
get_state/2,
|
get_state/2,
|
||||||
set_state/1,
|
set_state/1,
|
||||||
@ -160,6 +161,9 @@ get_subscriptions(NodeId, Owner) ->
|
|||||||
set_subscriptions(NodeId, Owner, Subscription, SubId) ->
|
set_subscriptions(NodeId, Owner, Subscription, SubId) ->
|
||||||
node_hometree:set_subscriptions(NodeId, Owner, Subscription, SubId).
|
node_hometree:set_subscriptions(NodeId, Owner, Subscription, SubId).
|
||||||
|
|
||||||
|
get_pending_nodes(Host, Owner) ->
|
||||||
|
node_hometree:get_pending_nodes(Host, Owner).
|
||||||
|
|
||||||
get_states(NodeId) ->
|
get_states(NodeId) ->
|
||||||
node_hometree:get_states(NodeId).
|
node_hometree:get_states(NodeId).
|
||||||
|
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
get_node_subscriptions/1,
|
get_node_subscriptions/1,
|
||||||
get_subscriptions/2,
|
get_subscriptions/2,
|
||||||
set_subscriptions/4,
|
set_subscriptions/4,
|
||||||
|
get_pending_nodes/2,
|
||||||
get_states/1,
|
get_states/1,
|
||||||
get_state/2,
|
get_state/2,
|
||||||
set_state/1,
|
set_state/1,
|
||||||
@ -162,6 +163,9 @@ get_subscriptions(NodeId, Owner) ->
|
|||||||
set_subscriptions(NodeId, Owner, Subscription, SubId) ->
|
set_subscriptions(NodeId, Owner, Subscription, SubId) ->
|
||||||
node_hometree:set_subscriptions(NodeId, Owner, Subscription, SubId).
|
node_hometree:set_subscriptions(NodeId, Owner, Subscription, SubId).
|
||||||
|
|
||||||
|
get_pending_nodes(Host, Owner) ->
|
||||||
|
node_hometree:get_pending_nodes(Host, Owner).
|
||||||
|
|
||||||
get_states(NodeId) ->
|
get_states(NodeId) ->
|
||||||
node_hometree:get_states(NodeId).
|
node_hometree:get_states(NodeId).
|
||||||
|
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
get_node_subscriptions/1,
|
get_node_subscriptions/1,
|
||||||
get_subscriptions/2,
|
get_subscriptions/2,
|
||||||
set_subscriptions/4,
|
set_subscriptions/4,
|
||||||
|
get_pending_nodes/2,
|
||||||
get_states/1,
|
get_states/1,
|
||||||
get_state/2,
|
get_state/2,
|
||||||
set_state/1,
|
set_state/1,
|
||||||
@ -161,6 +162,9 @@ get_subscriptions(NodeId, Owner) ->
|
|||||||
set_subscriptions(NodeId, Owner, Subscription, SubId) ->
|
set_subscriptions(NodeId, Owner, Subscription, SubId) ->
|
||||||
node_hometree:set_subscriptions(NodeId, Owner, Subscription, SubId).
|
node_hometree:set_subscriptions(NodeId, Owner, Subscription, SubId).
|
||||||
|
|
||||||
|
get_pending_nodes(Host, Owner) ->
|
||||||
|
node_hometree:get_pending_nodes(Host, Owner).
|
||||||
|
|
||||||
get_states(NodeId) ->
|
get_states(NodeId) ->
|
||||||
node_hometree:get_states(NodeId).
|
node_hometree:get_states(NodeId).
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
get_node_subscriptions/1,
|
get_node_subscriptions/1,
|
||||||
get_subscriptions/2,
|
get_subscriptions/2,
|
||||||
set_subscriptions/4,
|
set_subscriptions/4,
|
||||||
|
get_pending_nodes/2,
|
||||||
get_states/1,
|
get_states/1,
|
||||||
get_state/2,
|
get_state/2,
|
||||||
set_state/1,
|
set_state/1,
|
||||||
@ -139,6 +140,9 @@ get_subscriptions(NodeID, Owner) ->
|
|||||||
set_subscriptions(NodeID, Owner, Subscription, SubID) ->
|
set_subscriptions(NodeID, Owner, Subscription, SubID) ->
|
||||||
node_hometree:set_subscriptions(NodeID, Owner, Subscription, SubID).
|
node_hometree:set_subscriptions(NodeID, Owner, Subscription, SubID).
|
||||||
|
|
||||||
|
get_pending_nodes(Host, Owner) ->
|
||||||
|
node_hometree:get_pending_nodes(Host, Owner).
|
||||||
|
|
||||||
get_states(NodeID) ->
|
get_states(NodeID) ->
|
||||||
node_hometree:get_states(NodeID).
|
node_hometree:get_states(NodeID).
|
||||||
|
|
||||||
|
@ -57,6 +57,7 @@
|
|||||||
get_node_subscriptions/1,
|
get_node_subscriptions/1,
|
||||||
get_subscriptions/2,
|
get_subscriptions/2,
|
||||||
set_subscriptions/4,
|
set_subscriptions/4,
|
||||||
|
get_pending_nodes/2,
|
||||||
get_states/1,
|
get_states/1,
|
||||||
get_state/2,
|
get_state/2,
|
||||||
set_state/1,
|
set_state/1,
|
||||||
@ -165,6 +166,9 @@ get_subscriptions(_NodeId, _Owner) ->
|
|||||||
set_subscriptions(NodeId, Owner, Subscription, SubId) ->
|
set_subscriptions(NodeId, Owner, Subscription, SubId) ->
|
||||||
node_hometree:set_subscriptions(NodeId, Owner, Subscription, SubId).
|
node_hometree:set_subscriptions(NodeId, Owner, Subscription, SubId).
|
||||||
|
|
||||||
|
get_pending_nodes(Host, Owner) ->
|
||||||
|
node_hometree:get_pending_nodes(Host, Owner).
|
||||||
|
|
||||||
get_states(NodeId) ->
|
get_states(NodeId) ->
|
||||||
node_hometree:get_states(NodeId).
|
node_hometree:get_states(NodeId).
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
get_node_subscriptions/1,
|
get_node_subscriptions/1,
|
||||||
get_subscriptions/2,
|
get_subscriptions/2,
|
||||||
set_subscriptions/4,
|
set_subscriptions/4,
|
||||||
|
get_pending_nodes/2,
|
||||||
get_states/1,
|
get_states/1,
|
||||||
get_state/2,
|
get_state/2,
|
||||||
set_state/1,
|
set_state/1,
|
||||||
@ -148,6 +149,9 @@ get_subscriptions(NodeId, Owner) ->
|
|||||||
set_subscriptions(NodeId, Owner, Subscription, SubId) ->
|
set_subscriptions(NodeId, Owner, Subscription, SubId) ->
|
||||||
node_hometree:set_subscriptions(NodeId, Owner, Subscription, SubId).
|
node_hometree:set_subscriptions(NodeId, Owner, Subscription, SubId).
|
||||||
|
|
||||||
|
get_pending_nodes(Host, Owner) ->
|
||||||
|
node_hometree:get_pending_nodes(Host, Owner).
|
||||||
|
|
||||||
get_states(NodeId) ->
|
get_states(NodeId) ->
|
||||||
node_hometree:get_states(NodeId).
|
node_hometree:get_states(NodeId).
|
||||||
|
|
||||||
|
@ -66,6 +66,7 @@
|
|||||||
get_node_subscriptions/1,
|
get_node_subscriptions/1,
|
||||||
get_subscriptions/2,
|
get_subscriptions/2,
|
||||||
set_subscriptions/4,
|
set_subscriptions/4,
|
||||||
|
get_pending_nodes/2,
|
||||||
get_states/1,
|
get_states/1,
|
||||||
get_state/2,
|
get_state/2,
|
||||||
set_state/1,
|
set_state/1,
|
||||||
@ -155,6 +156,7 @@ features() ->
|
|||||||
"access-authorize",
|
"access-authorize",
|
||||||
"delete-nodes",
|
"delete-nodes",
|
||||||
"delete-items",
|
"delete-items",
|
||||||
|
"get-pending",
|
||||||
"instant-nodes",
|
"instant-nodes",
|
||||||
"manage-subscriptions",
|
"manage-subscriptions",
|
||||||
"modify-affiliations",
|
"modify-affiliations",
|
||||||
@ -658,10 +660,8 @@ get_entity_subscriptions(Host, Owner) ->
|
|||||||
Reply = lists:foldl(fun(#pubsub_state{stateid = {J, N}, subscriptions = Ss}, Acc) ->
|
Reply = lists:foldl(fun(#pubsub_state{stateid = {J, N}, subscriptions = Ss}, Acc) ->
|
||||||
case NodeTree:get_node(N) of
|
case NodeTree:get_node(N) of
|
||||||
#pubsub_node{nodeid = {Host, _}} = Node ->
|
#pubsub_node{nodeid = {Host, _}} = Node ->
|
||||||
lists:foldl(fun({subscribed, SubID}, Acc2) ->
|
lists:foldl(fun({Sub, SubID}, Acc2) ->
|
||||||
[{Node, subscribed, SubID, J} | Acc2];
|
[{Node, Sub, SubID, J} | Acc2];
|
||||||
({pending, _SubID}, Acc2) ->
|
|
||||||
[{Node, pending, J} | Acc2];
|
|
||||||
(S, Acc2) ->
|
(S, Acc2) ->
|
||||||
[{Node, S, J} | Acc2]
|
[{Node, S, J} | Acc2]
|
||||||
end, Acc, Ss);
|
end, Acc, Ss);
|
||||||
@ -676,10 +676,13 @@ get_node_subscriptions(NodeId) ->
|
|||||||
%% TODO: get rid of cases to handle non-list subscriptions
|
%% TODO: get rid of cases to handle non-list subscriptions
|
||||||
case Subscriptions of
|
case Subscriptions of
|
||||||
[_|_] ->
|
[_|_] ->
|
||||||
lists:map(fun({subscribed, SubID}) -> {J, subscribed, SubID};
|
lists:foldl(fun({S, SubID}, Acc) ->
|
||||||
({pending, _SubID}) -> {J, pending};
|
[{J, S, SubID} | Acc];
|
||||||
(S) -> {J, S}
|
(S, Acc) ->
|
||||||
end, Subscriptions);
|
[{J, S} | Acc]
|
||||||
|
end, [], Subscriptions);
|
||||||
|
[] ->
|
||||||
|
[];
|
||||||
_ ->
|
_ ->
|
||||||
[{J, none}]
|
[{J, none}]
|
||||||
end
|
end
|
||||||
@ -695,32 +698,32 @@ set_subscriptions(NodeId, Owner, none, SubId) ->
|
|||||||
SubKey = jlib:jid_tolower(Owner),
|
SubKey = jlib:jid_tolower(Owner),
|
||||||
SubState = get_state(NodeId, SubKey),
|
SubState = get_state(NodeId, SubKey),
|
||||||
case {SubId, SubState#pubsub_state.subscriptions} of
|
case {SubId, SubState#pubsub_state.subscriptions} of
|
||||||
{_, []} ->
|
{_, []} ->
|
||||||
{error, ?ERR_ITEM_NOT_FOUND};
|
{error, ?ERR_ITEM_NOT_FOUND};
|
||||||
{"", [{_, SID}]} ->
|
{"", [{_, SID}]} ->
|
||||||
unsub_with_subid(NodeId, SID, SubState);
|
unsub_with_subid(NodeId, SID, SubState);
|
||||||
{"", [_|_]} ->
|
{"", [_|_]} ->
|
||||||
{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")};
|
{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")};
|
||||||
_ ->
|
_ ->
|
||||||
unsub_with_subid(NodeId, SubId, SubState)
|
unsub_with_subid(NodeId, SubId, SubState)
|
||||||
end;
|
end;
|
||||||
set_subscriptions(NodeId, Owner, Subscription, SubId) ->
|
set_subscriptions(NodeId, Owner, Subscription, SubId) ->
|
||||||
SubKey = jlib:jid_tolower(Owner),
|
SubKey = jlib:jid_tolower(Owner),
|
||||||
SubState = get_state(NodeId, SubKey),
|
SubState = get_state(NodeId, SubKey),
|
||||||
case {SubId, SubState#pubsub_state.subscriptions} of
|
case {SubId, SubState#pubsub_state.subscriptions} of
|
||||||
{_, []} ->
|
{_, []} ->
|
||||||
{error, ?ERR_ITEM_NOT_FOUND};
|
{error, ?ERR_ITEM_NOT_FOUND};
|
||||||
{"", [{_, SID}]} ->
|
{"", [{_, SID}]} ->
|
||||||
replace_subscription({Subscription, SID}, SubState);
|
replace_subscription({Subscription, SID}, SubState);
|
||||||
{"", [_|_]} ->
|
{"", [_|_]} ->
|
||||||
{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")};
|
{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")};
|
||||||
_ ->
|
_ ->
|
||||||
replace_subscription({Subscription, SubId}, SubState)
|
replace_subscription({Subscription, SubId}, SubState)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
replace_subscription(NewSub, SubState) ->
|
replace_subscription(NewSub, SubState) ->
|
||||||
NewSubs = replace_subscription(NewSub,
|
NewSubs = replace_subscription(NewSub,
|
||||||
SubState#pubsub_state.subscriptions, []),
|
SubState#pubsub_state.subscriptions, []),
|
||||||
set_state(SubState#pubsub_state{subscriptions = NewSubs}).
|
set_state(SubState#pubsub_state{subscriptions = NewSubs}).
|
||||||
|
|
||||||
replace_subscription(_, [], Acc) ->
|
replace_subscription(_, [], Acc) ->
|
||||||
@ -730,9 +733,9 @@ replace_subscription({Sub, SubID}, [{_, SubID} | T], Acc) ->
|
|||||||
|
|
||||||
unsub_with_subid(NodeId, SubId, SubState) ->
|
unsub_with_subid(NodeId, SubId, SubState) ->
|
||||||
pubsub_subscription:unsubscribe_node(SubState#pubsub_state.stateid,
|
pubsub_subscription:unsubscribe_node(SubState#pubsub_state.stateid,
|
||||||
NodeId, SubId),
|
NodeId, SubId),
|
||||||
NewSubs = lists:filter(fun ({_, SID}) -> SubId =/= SID end,
|
NewSubs = lists:filter(fun ({_, SID}) -> SubId =/= SID end,
|
||||||
SubState#pubsub_state.subscriptions),
|
SubState#pubsub_state.subscriptions),
|
||||||
case {NewSubs, SubState#pubsub_state.affiliation} of
|
case {NewSubs, SubState#pubsub_state.affiliation} of
|
||||||
{[], none} ->
|
{[], none} ->
|
||||||
del_state(NodeId, element(1, SubState#pubsub_state.stateid));
|
del_state(NodeId, element(1, SubState#pubsub_state.stateid));
|
||||||
@ -740,6 +743,53 @@ unsub_with_subid(NodeId, SubId, SubState) ->
|
|||||||
set_state(SubState#pubsub_state{subscriptions = NewSubs})
|
set_state(SubState#pubsub_state{subscriptions = NewSubs})
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
%% @spec (Host, Owner) -> {result, [Node]} | {error, Reason}
|
||||||
|
%% Host = host()
|
||||||
|
%% Owner = jid()
|
||||||
|
%% Node = pubsubNode()
|
||||||
|
%% @doc <p>Returns a list of Owner's nodes on Host with pending
|
||||||
|
%% subscriptions.</p>
|
||||||
|
get_pending_nodes(Host, Owner) ->
|
||||||
|
GenKey = jlib:jid_remove_resource(jlib:jid_tolower(Owner)),
|
||||||
|
States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'},
|
||||||
|
affiliation = owner,
|
||||||
|
_ = '_'}),
|
||||||
|
NodeIDs = [ID || #pubsub_state{stateid = {_, ID}} <- States],
|
||||||
|
NodeTree = case ets:lookup(gen_mod:get_module_proc(Host, config), nodetree) of
|
||||||
|
[{nodetree, N}] -> N;
|
||||||
|
_ -> nodetree_tree
|
||||||
|
end,
|
||||||
|
Reply = mnesia:foldl(fun(#pubsub_state{stateid = {_, NID}} = S, Acc) ->
|
||||||
|
case lists:member(NID, NodeIDs) of
|
||||||
|
true ->
|
||||||
|
case get_nodes_helper(NodeTree, S) of
|
||||||
|
{value, Node} -> [Node | Acc];
|
||||||
|
false -> Acc
|
||||||
|
end;
|
||||||
|
false ->
|
||||||
|
Acc
|
||||||
|
end
|
||||||
|
end, [], pubsub_state),
|
||||||
|
{result, Reply}.
|
||||||
|
|
||||||
|
get_nodes_helper(NodeTree,
|
||||||
|
#pubsub_state{stateid = {_, N}, subscriptions = Subs}) ->
|
||||||
|
HasPending = fun ({pending, _}) -> true;
|
||||||
|
(pending) -> true;
|
||||||
|
(_) -> false
|
||||||
|
end,
|
||||||
|
case lists:any(HasPending, Subs) of
|
||||||
|
true ->
|
||||||
|
case NodeTree:get_node(N) of
|
||||||
|
#pubsub_node{nodeid = {_, Node}} ->
|
||||||
|
{value, Node};
|
||||||
|
_ ->
|
||||||
|
false
|
||||||
|
end;
|
||||||
|
false ->
|
||||||
|
false
|
||||||
|
end.
|
||||||
|
|
||||||
%% @spec (NodeId) -> [States] | []
|
%% @spec (NodeId) -> [States] | []
|
||||||
%% NodeId = mod_pubsub:pubsubNodeId()
|
%% NodeId = mod_pubsub:pubsubNodeId()
|
||||||
%% @doc Returns the list of stored states for a given node.
|
%% @doc Returns the list of stored states for a given node.
|
||||||
|
@ -62,6 +62,7 @@
|
|||||||
get_node_subscriptions/1,
|
get_node_subscriptions/1,
|
||||||
get_subscriptions/2,
|
get_subscriptions/2,
|
||||||
set_subscriptions/4,
|
set_subscriptions/4,
|
||||||
|
get_pending_nodes/2,
|
||||||
get_states/1,
|
get_states/1,
|
||||||
get_state/2,
|
get_state/2,
|
||||||
set_state/1,
|
set_state/1,
|
||||||
@ -169,6 +170,9 @@ get_subscriptions(NodeId, Owner) ->
|
|||||||
set_subscriptions(NodeId, Owner, Subscription, SubId) ->
|
set_subscriptions(NodeId, Owner, Subscription, SubId) ->
|
||||||
node_pep:set_subscriptions(NodeId, Owner, Subscription, SubId).
|
node_pep:set_subscriptions(NodeId, Owner, Subscription, SubId).
|
||||||
|
|
||||||
|
get_pending_nodes(Host, Owner) ->
|
||||||
|
node_hometree:get_pending_nodes(Host, Owner).
|
||||||
|
|
||||||
get_states(NodeId) ->
|
get_states(NodeId) ->
|
||||||
node_pep:get_states(NodeId).
|
node_pep:get_states(NodeId).
|
||||||
|
|
||||||
|
@ -55,6 +55,7 @@
|
|||||||
get_node_subscriptions/1,
|
get_node_subscriptions/1,
|
||||||
get_subscriptions/2,
|
get_subscriptions/2,
|
||||||
set_subscriptions/4,
|
set_subscriptions/4,
|
||||||
|
get_pending_nodes/2,
|
||||||
get_states/1,
|
get_states/1,
|
||||||
get_state/2,
|
get_state/2,
|
||||||
set_state/1,
|
set_state/1,
|
||||||
@ -236,6 +237,9 @@ get_subscriptions(NodeId, Owner) ->
|
|||||||
set_subscriptions(NodeId, Owner, Subscription, SubId) ->
|
set_subscriptions(NodeId, Owner, Subscription, SubId) ->
|
||||||
node_hometree:set_subscriptions(NodeId, Owner, Subscription, SubId).
|
node_hometree:set_subscriptions(NodeId, Owner, Subscription, SubId).
|
||||||
|
|
||||||
|
get_pending_nodes(Host, Owner) ->
|
||||||
|
node_hometree:get_pending_nodes(Host, Owner).
|
||||||
|
|
||||||
get_states(NodeId) ->
|
get_states(NodeId) ->
|
||||||
node_hometree:get_states(NodeId).
|
node_hometree:get_states(NodeId).
|
||||||
|
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
get_node_subscriptions/1,
|
get_node_subscriptions/1,
|
||||||
get_subscriptions/2,
|
get_subscriptions/2,
|
||||||
set_subscriptions/4,
|
set_subscriptions/4,
|
||||||
|
get_pending_nodes/2,
|
||||||
get_states/1,
|
get_states/1,
|
||||||
get_state/2,
|
get_state/2,
|
||||||
set_state/1,
|
set_state/1,
|
||||||
@ -165,6 +166,9 @@ get_subscriptions(NodeId, Owner) ->
|
|||||||
set_subscriptions(NodeId, Owner, Subscription, SubId) ->
|
set_subscriptions(NodeId, Owner, Subscription, SubId) ->
|
||||||
node_hometree:set_subscriptions(NodeId, Owner, Subscription, SubId).
|
node_hometree:set_subscriptions(NodeId, Owner, Subscription, SubId).
|
||||||
|
|
||||||
|
get_pending_nodes(Host, Owner) ->
|
||||||
|
node_hometree:get_pending_nodes(Host, Owner).
|
||||||
|
|
||||||
get_states(NodeId) ->
|
get_states(NodeId) ->
|
||||||
node_hometree:get_states(NodeId).
|
node_hometree:get_states(NodeId).
|
||||||
|
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
get_node_subscriptions/1,
|
get_node_subscriptions/1,
|
||||||
get_subscriptions/2,
|
get_subscriptions/2,
|
||||||
set_subscriptions/4,
|
set_subscriptions/4,
|
||||||
|
get_pending_nodes/2,
|
||||||
get_states/1,
|
get_states/1,
|
||||||
get_state/2,
|
get_state/2,
|
||||||
set_state/1,
|
set_state/1,
|
||||||
@ -161,6 +162,9 @@ get_subscriptions(NodeId, Owner) ->
|
|||||||
set_subscriptions(NodeId, Owner, Subscription, SubId) ->
|
set_subscriptions(NodeId, Owner, Subscription, SubId) ->
|
||||||
node_hometree:set_subscriptions(NodeId, Owner, Subscription, SubId).
|
node_hometree:set_subscriptions(NodeId, Owner, Subscription, SubId).
|
||||||
|
|
||||||
|
get_pending_nodes(Host, Owner) ->
|
||||||
|
node_hometree:get_pending_nodes(Host, Owner).
|
||||||
|
|
||||||
get_states(NodeId) ->
|
get_states(NodeId) ->
|
||||||
node_hometree:get_states(NodeId).
|
node_hometree:get_states(NodeId).
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user