]> granicus.if.org Git - ejabberd/commitdiff
Implement pubsub#get-pending Ad Hoc Command (EJAB-955) (thanks to Brian Cully)
authorChristophe Romain <christophe.romain@process-one.net>
Mon, 20 Jul 2009 08:53:56 +0000 (08:53 +0000)
committerChristophe Romain <christophe.romain@process-one.net>
Mon, 20 Jul 2009 08:53:56 +0000 (08:53 +0000)
SVN Revision: 2372

14 files changed:
src/jlib.hrl
src/mod_pubsub/gen_pubsub_node.erl
src/mod_pubsub/mod_pubsub.erl
src/mod_pubsub/node.template
src/mod_pubsub/node_buddy.erl
src/mod_pubsub/node_club.erl
src/mod_pubsub/node_dag.erl
src/mod_pubsub/node_dispatch.erl
src/mod_pubsub/node_flat.erl
src/mod_pubsub/node_hometree.erl
src/mod_pubsub/node_mb.erl
src/mod_pubsub/node_pep.erl
src/mod_pubsub/node_private.erl
src/mod_pubsub/node_public.erl

index 955670e33f6e432e7fa834aa554c6fc152a55164..8051fc0a91df39128f7d6b9dd9aad30bfbf09dfb 100644 (file)
@@ -54,6 +54,7 @@
 -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_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_BYTESTREAMS,  "http://jabber.org/protocol/bytestreams").
 -define(NS_ADMIN,        "http://jabber.org/protocol/admin").
index dbf7e25d59699d12cfefe2035910bc8bf178fab4..3762d4a44453affd6d9db4181f8896a81fba5002 100644 (file)
@@ -59,6 +59,7 @@ behaviour_info(callbacks) ->
      {get_entity_subscriptions, 2},
      {get_subscriptions, 2},
      {set_subscriptions, 4},
+     {get_pending_nodes, 2},
      {get_states, 1},
      {get_state, 2},
      {set_state, 1},
index 58e57150904bca994ffd4c6f20bc632acd7bf23c..d8e193548cbc095a800813f8f76fbccfc0f5f7e6 100644 (file)
@@ -53,6 +53,7 @@
 -behaviour(gen_mod).
 
 -include("ejabberd.hrl").
+-include("adhoc.hrl").
 -include("jlib.hrl").
 -include("pubsub.hrl").
 
@@ -945,6 +946,15 @@ do_route(ServerHost, Access, Plugins, Host, From, To, Packet) ->
                                        sub_el = [{xmlelement, "vCard", [{"xmlns", XMLNS}],
                                                   iq_get_vcard(Lang)}]},
                            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{} ->
                            Err = jlib:make_error_reply(
                                    Packet,
@@ -1282,6 +1292,140 @@ iq_pubsub_owner(Host, ServerHost, From, IQType, SubEl, Lang) ->
            {error, ?ERR_BAD_REQUEST}
     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
 
 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;
                            ({_, none, _}) ->
                                [];
-                           ({#pubsub_node{nodeid = {_, SubsNode}}, subscribed, SubID, SubJID}) ->
+                           ({#pubsub_node{nodeid = {_, SubsNode}}, Subscription, SubID, SubJID}) ->
                                case Node of
                                [] ->
                                 [{xmlelement, "subscription",
                                   [{"jid", jlib:jid_to_string(SubJID)},
                                    {"subid", SubID},
-                                   {"subscription", subscription_to_string(subscribed)}|nodeAttr(SubsNode)],
+                                   {"subscription", subscription_to_string(Subscription)}|nodeAttr(SubsNode)],
                                   []}];
                                SubsNode ->
                                 [{xmlelement, "subscription",
                                   [{"jid", jlib:jid_to_string(SubJID)},
                                    {"subid", SubID},
-                                   {"subscription", subscription_to_string(subscribed)}],
+                                   {"subscription", subscription_to_string(Subscription)}],
                                   []}];
                                _ ->
                                 []
@@ -2468,11 +2612,10 @@ get_subscriptions(Host, Node, JID) ->
                     end
             end,
     case transaction(Host, Node, Action, sync_dirty) of
-       {result, {_, []}} ->
-           {error, ?ERR_ITEM_NOT_FOUND};
        {result, {_, Subscriptions}} ->
            Entities = lists:flatmap(
                         fun({_, none}) -> [];
+                            ({_, pending, _}) -> [];
                            ({AJID, Subscription}) ->
                                 [{xmlelement, "subscription",
                                   [{"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) ->
     NewValue = [string_to_node(V) || V <- Value],
     ?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) ->
     % skip unknown field
     set_xoption(Opts, NewOpts).
@@ -3319,7 +3465,7 @@ features() ->
         % see plugin "delete-items",   % RECOMMENDED
         % see plugin "delete-nodes",   % RECOMMENDED
         % see plugin "filtered-notifications",   % RECOMMENDED
-        %TODO "get-pending",   % OPTIONAL
+        % see plugin "get-pending",   % OPTIONAL
         % see plugin "instant-nodes",   % RECOMMENDED
         "item-ids",   % RECOMMENDED
         "last-published",   % RECOMMENDED
index 08f2e08ed100b913929c8e9c77b5f9b44e6ed605..59de1dcb325417ed1ce03f1d9487eae31a97345b 100644 (file)
@@ -58,6 +58,7 @@
         get_node_subscriptions/1,
         get_subscriptions/2,
         set_subscriptions/4,
+        get_pending_nodes/2,
         get_states/1,
         get_state/2,
         set_state/1,
@@ -160,6 +161,9 @@ get_subscriptions(NodeId, Owner) ->
 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) ->
     node_hometree:get_states(NodeId).
 
index b3aea6f4a9c3e6cd1a20e54f9c917f2fec0424c0..5283ca5f09238a8ea57af65c51ea8a0f6c19a795 100644 (file)
@@ -59,6 +59,7 @@
         get_node_subscriptions/1,
         get_subscriptions/2,
         set_subscriptions/4,
+        get_pending_nodes/2,
         get_states/1,
         get_state/2,
         set_state/1,
@@ -162,6 +163,9 @@ get_subscriptions(NodeId, Owner) ->
 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) ->
     node_hometree:get_states(NodeId).
 
index e3c16c630be117eb4df08cab344827b2ca8ef62e..a268cb9dc231f0db0bfdd5f4e33bad5ee2b314a8 100644 (file)
@@ -59,6 +59,7 @@
         get_node_subscriptions/1,
         get_subscriptions/2,
         set_subscriptions/4,
+        get_pending_nodes/2,
         get_states/1,
         get_state/2,
         set_state/1,
@@ -161,6 +162,9 @@ get_subscriptions(NodeId, Owner) ->
 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) ->
     node_hometree:get_states(NodeId).
 
index 2ffb70df2e0e900c5c080dc1ac382980dfcb9e7f..f28c338d88b10b720b2246a27cd9395e70ad5032 100644 (file)
@@ -43,6 +43,7 @@
         get_node_subscriptions/1,
         get_subscriptions/2,
         set_subscriptions/4,
+        get_pending_nodes/2,
         get_states/1,
         get_state/2,
         set_state/1,
@@ -139,6 +140,9 @@ get_subscriptions(NodeID, Owner) ->
 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) ->
     node_hometree:get_states(NodeID).
 
index 698d2559acf43f469c87caf34056677b061c9a85..59a9dd85fbc2dbb88ce81d1964294639d6ecbc6d 100644 (file)
@@ -57,6 +57,7 @@
         get_node_subscriptions/1,
         get_subscriptions/2,
         set_subscriptions/4,
+        get_pending_nodes/2,
         get_states/1,
         get_state/2,
         set_state/1,
@@ -165,6 +166,9 @@ get_subscriptions(_NodeId, _Owner) ->
 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) ->
     node_hometree:get_states(NodeId).
 
index 4a89abdc6577418043ed50be160e7c082943361d..05c0f9c3b8dbbce45eb493d48e179b428057dedb 100644 (file)
@@ -50,6 +50,7 @@
         get_node_subscriptions/1,
         get_subscriptions/2,
         set_subscriptions/4,
+        get_pending_nodes/2,
         get_states/1,
         get_state/2,
         set_state/1,
@@ -148,6 +149,9 @@ get_subscriptions(NodeId, Owner) ->
 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) ->
     node_hometree:get_states(NodeId).
 
index eda7fef7f2a684be351c0cdbbd04b8dfbc0202c4..604945244e6979f31dc202d6f5637dce8406c905 100644 (file)
@@ -66,6 +66,7 @@
         get_node_subscriptions/1,
         get_subscriptions/2,
         set_subscriptions/4,
+        get_pending_nodes/2,
         get_states/1,
         get_state/2,
         set_state/1,
@@ -155,6 +156,7 @@ features() ->
      "access-authorize",
      "delete-nodes",
      "delete-items",
+     "get-pending",
      "instant-nodes",
      "manage-subscriptions",
      "modify-affiliations",
@@ -658,10 +660,8 @@ get_entity_subscriptions(Host, Owner) ->
     Reply = lists:foldl(fun(#pubsub_state{stateid = {J, N}, subscriptions = Ss}, Acc) ->
        case NodeTree:get_node(N) of
            #pubsub_node{nodeid = {Host, _}} = Node ->
-                       lists:foldl(fun({subscribed, SubID}, Acc2) ->
-                                           [{Node, subscribed, SubID, J} | Acc2];
-                                       ({pending, _SubID}, Acc2) ->
-                                           [{Node, pending, J} | Acc2];
+                       lists:foldl(fun({Sub, SubID}, Acc2) ->
+                                           [{Node, Sub, SubID, J} | Acc2];
                                        (S, Acc2) ->
                                            [{Node, S, J} | Acc2]
                                    end, Acc, Ss);
@@ -676,10 +676,13 @@ get_node_subscriptions(NodeId) ->
                 %% TODO: get rid of cases to handle non-list subscriptions
                 case Subscriptions of
                    [_|_] ->
-                       lists:map(fun({subscribed, SubID}) -> {J, subscribed, SubID};
-                                    ({pending, _SubID}) -> {J, pending};
-                                    (S) -> {J, S}
-                               end, Subscriptions);
+                       lists:foldl(fun({S, SubID}, Acc) ->
+                                            [{J, S, SubID} | Acc];
+                                       (S, Acc) ->
+                                            [{J, S} | Acc]
+                               end, [], Subscriptions);
+                    [] ->
+                         [];
                    _ ->
                         [{J, none}]
                 end
@@ -695,32 +698,32 @@ set_subscriptions(NodeId, Owner, none, SubId) ->
     SubKey = jlib:jid_tolower(Owner),
     SubState = get_state(NodeId, SubKey),
     case {SubId, SubState#pubsub_state.subscriptions} of
-        {_, []} ->
-            {error, ?ERR_ITEM_NOT_FOUND};
-        {"", [{_, SID}]} ->
-            unsub_with_subid(NodeId, SID, SubState);
-        {"", [_|_]} ->
-            {error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")};
-        _ ->
-            unsub_with_subid(NodeId, SubId, SubState)
+       {_, []} ->
+           {error, ?ERR_ITEM_NOT_FOUND};
+       {"", [{_, SID}]} ->
+           unsub_with_subid(NodeId, SID, SubState);
+       {"", [_|_]} ->
+           {error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")};
+       _ ->
+           unsub_with_subid(NodeId, SubId, SubState)
     end;
 set_subscriptions(NodeId, Owner, Subscription, SubId) ->
     SubKey = jlib:jid_tolower(Owner),
     SubState = get_state(NodeId, SubKey),
     case {SubId, SubState#pubsub_state.subscriptions} of
-        {_, []} ->
-            {error, ?ERR_ITEM_NOT_FOUND};
-        {"", [{_, SID}]} ->
-            replace_subscription({Subscription, SID}, SubState);
-        {"", [_|_]} ->
-            {error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")};
-         _ ->
-            replace_subscription({Subscription, SubId}, SubState)
+       {_, []} ->
+           {error, ?ERR_ITEM_NOT_FOUND};
+       {"", [{_, SID}]} ->
+           replace_subscription({Subscription, SID}, SubState);
+       {"", [_|_]} ->
+           {error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")};
+       _ ->
+           replace_subscription({Subscription, SubId}, SubState)
     end.
 
 replace_subscription(NewSub, SubState) ->
     NewSubs = replace_subscription(NewSub,
-                                   SubState#pubsub_state.subscriptions, []),
+                                  SubState#pubsub_state.subscriptions, []),
     set_state(SubState#pubsub_state{subscriptions = NewSubs}).
 
 replace_subscription(_, [], Acc) ->
@@ -730,9 +733,9 @@ replace_subscription({Sub, SubID}, [{_, SubID} | T], Acc) ->
 
 unsub_with_subid(NodeId, SubId, SubState) ->
     pubsub_subscription:unsubscribe_node(SubState#pubsub_state.stateid,
-                                         NodeId, SubId),
+                                        NodeId, SubId),
     NewSubs = lists:filter(fun ({_, SID}) -> SubId =/= SID end,
-                           SubState#pubsub_state.subscriptions),
+                          SubState#pubsub_state.subscriptions),
     case {NewSubs, SubState#pubsub_state.affiliation} of
        {[], none} ->
            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})
     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] | []
 %%      NodeId = mod_pubsub:pubsubNodeId()
 %% @doc Returns the list of stored states for a given node.
index b7ac76238cce8cb9b7489769d47909cdafdca4d3..beef44996cd5ffe7c9d84d3fe63c4823203fe2da 100644 (file)
@@ -62,6 +62,7 @@
         get_node_subscriptions/1,
         get_subscriptions/2,
         set_subscriptions/4,
+        get_pending_nodes/2,
         get_states/1,
         get_state/2,
         set_state/1,
@@ -169,6 +170,9 @@ get_subscriptions(NodeId, Owner) ->
 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) ->
     node_pep:get_states(NodeId).
 
index 57e30fecbcf6a94e279a5488fc61912ad525853b..b811ee58b6cb34ab6a0693c1d868627c730b51ff 100644 (file)
@@ -55,6 +55,7 @@
         get_node_subscriptions/1,
         get_subscriptions/2,
         set_subscriptions/4,
+        get_pending_nodes/2,
         get_states/1,
         get_state/2,
         set_state/1,
@@ -236,6 +237,9 @@ get_subscriptions(NodeId, Owner) ->
 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) ->
     node_hometree:get_states(NodeId).
 
index f4d4c8deaacaa304d013254695f391b52838be30..ba34bcb2fa953e71f6c609d1cd09ddb518e85a76 100644 (file)
@@ -59,6 +59,7 @@
         get_node_subscriptions/1,
         get_subscriptions/2,
         set_subscriptions/4,
+        get_pending_nodes/2,
         get_states/1,
         get_state/2,
         set_state/1,
@@ -165,6 +166,9 @@ get_subscriptions(NodeId, Owner) ->
 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) ->
     node_hometree:get_states(NodeId).
 
index fa806b7120a331bdece1c8dcbfd9de660551256a..c2bbe70e6f24b269af8158e1eb51cf1a1696160d 100644 (file)
@@ -59,6 +59,7 @@
         get_node_subscriptions/1,
         get_subscriptions/2,
         set_subscriptions/4,
+        get_pending_nodes/2,
         get_states/1,
         get_state/2,
         set_state/1,
@@ -161,6 +162,9 @@ get_subscriptions(NodeId, Owner) ->
 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) ->
     node_hometree:get_states(NodeId).