mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-26 16:26:24 +01:00
fix dializer warnings (thanks to Karim Gemayel)
This commit is contained in:
parent
349c44fcc0
commit
ee861e650d
@ -57,119 +57,408 @@
|
||||
path_to_node/1]).
|
||||
|
||||
|
||||
-spec(init/3 ::
|
||||
(
|
||||
Host :: string(),
|
||||
ServerHost :: string(),
|
||||
Opts :: [{Key::atom(), Value::term()}])
|
||||
-> 'ok'
|
||||
).
|
||||
|
||||
init(Host, ServerHost, Opts) ->
|
||||
node_flat:init(Host, ServerHost, Opts).
|
||||
|
||||
|
||||
-spec(terminate/2 ::
|
||||
(
|
||||
Host :: string(),
|
||||
ServerHost :: string())
|
||||
-> 'ok'
|
||||
).
|
||||
|
||||
terminate(Host, ServerHost) ->
|
||||
node_flat:terminate(Host, ServerHost).
|
||||
|
||||
|
||||
-spec(options/0 :: () -> [nodeOption()]).
|
||||
|
||||
options() ->
|
||||
[{node_type, leaf} | node_flat:options()].
|
||||
[{'node_type', 'leaf'} | node_flat:options()].
|
||||
|
||||
|
||||
-spec(features/0 :: () -> [Feature::string()]).
|
||||
|
||||
features() ->
|
||||
["multi-collection" | node_flat:features()].
|
||||
|
||||
create_node_permission(_Host, _ServerHost, _Node, _ParentNode,
|
||||
_Owner, _Access) ->
|
||||
|
||||
-spec(create_node_permission/6 ::
|
||||
(
|
||||
Host :: hostPubsub(),
|
||||
ServerHost :: string(),
|
||||
NodeId :: nodeId(),
|
||||
ParentNodeId :: nodeId(),
|
||||
JID :: jidEntity(),
|
||||
Access :: atom())
|
||||
-> {'result', 'true'}
|
||||
).
|
||||
|
||||
create_node_permission(_Host, _ServerHost, _NodeId, _ParentNodeId,
|
||||
_JID, _Access) ->
|
||||
{result, true}.
|
||||
|
||||
create_node(NodeId, Owner) ->
|
||||
node_flat:create_node(NodeId, Owner).
|
||||
|
||||
delete_node(Removed) ->
|
||||
node_flat:delete_node(Removed).
|
||||
-spec(create_node/2 ::
|
||||
(
|
||||
NodeIdx :: nodeIdx(),
|
||||
JID :: jidEntity())
|
||||
-> {'result', {'default', 'broadcast'}}
|
||||
).
|
||||
|
||||
subscribe_node(NodeId, Sender, Subscriber, AccessModel,
|
||||
create_node(NodeIdx, JID) ->
|
||||
node_flat:create_node(NodeIdx, JID).
|
||||
|
||||
|
||||
-spec(delete_node/1 ::
|
||||
(
|
||||
Nodes :: [Node::pubsubNode()])
|
||||
-> {result, {'default', 'broadcast',
|
||||
Reply :: [{Node :: pubsubNode(),
|
||||
[{Owner :: bareUsr(),
|
||||
Subscriptions :: [{Subscription :: subscription(),
|
||||
SubId :: subId()}]}]}]}}
|
||||
).
|
||||
|
||||
delete_node(Nodes) ->
|
||||
node_flat:delete_node(Nodes).
|
||||
|
||||
|
||||
-spec(subscribe_node/8 ::
|
||||
(
|
||||
NodeIdx :: nodeIdx(),
|
||||
JID :: jidEntity(),
|
||||
Subscriber :: jidEntity(),
|
||||
AccessModel :: accessModel(),
|
||||
SendLast :: atom(),
|
||||
PresenceSubscription :: boolean(),
|
||||
RosterGroup :: boolean(),
|
||||
Options :: [nodeOption()])
|
||||
-> {'result', {'default',
|
||||
Subscription :: 'subscribed',
|
||||
SubId :: subId()}}
|
||||
| {'result', {'default',
|
||||
Subscription :: 'subscribed',
|
||||
SubId :: subId(),
|
||||
SendLast ::' send_last'}}
|
||||
| {'result', {'default',
|
||||
Subscription :: 'pending',
|
||||
SubId :: subId()}}
|
||||
| {'error', _} %% TODO add all error cases
|
||||
).
|
||||
|
||||
subscribe_node(NodeIdx, JID, Subscriber, AccessModel,
|
||||
SendLast, PresenceSubscription, RosterGroup, Options) ->
|
||||
node_flat:subscribe_node(NodeId, Sender, Subscriber, AccessModel,
|
||||
node_flat:subscribe_node(NodeIdx, JID, Subscriber, AccessModel,
|
||||
SendLast, PresenceSubscription, RosterGroup,
|
||||
Options).
|
||||
|
||||
unsubscribe_node(NodeId, Sender, Subscriber, SubId) ->
|
||||
node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubId).
|
||||
|
||||
publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) ->
|
||||
-spec(unsubscribe_node/4 ::
|
||||
(
|
||||
NodeIdx :: nodeIdx(),
|
||||
JID :: jidEntity(),
|
||||
Subscriber :: jidEntity(),
|
||||
SubId :: subId())
|
||||
-> {'result', 'default'} | {'error', _} %% TODO : add all error cases
|
||||
).
|
||||
|
||||
unsubscribe_node(NodeIdx, JID, Subscriber, SubId) ->
|
||||
node_flat:unsubscribe_node(NodeIdx, JID, Subscriber, SubId).
|
||||
|
||||
|
||||
-spec(publish_item/6 ::
|
||||
(
|
||||
NodeIdx :: nodeIdx(),
|
||||
JID :: jidEntity(),
|
||||
PublishModel :: atom(), %% TODO : make a generic publishMod() type
|
||||
MaxItems :: 'unlimited' | integer(),
|
||||
ItemId :: itemId(),
|
||||
Payload :: payload())
|
||||
-> {'result', {'default', 'broadcast', ItemIds :: [] | [itemId()]}}
|
||||
| {'error', _}
|
||||
).
|
||||
|
||||
publish_item(NodeIdx, JID, PublishModel, MaxItems, ItemId, Payload) ->
|
||||
%% TODO: should look up the NodeTree plugin here. There's no
|
||||
%% access to the Host of the request at this level, so for now we
|
||||
%% just use nodetree_dag.
|
||||
case nodetree_dag:get_node(NodeId) of
|
||||
case nodetree_dag:get_node(NodeIdx) of
|
||||
#pubsub_node{options = Options} ->
|
||||
case find_opt(node_type, Options) of
|
||||
collection ->
|
||||
case find_opt('node_type', Options) of
|
||||
'collection' ->
|
||||
{error, mod_pubsub:extended_error('not-allowed', "publish")};
|
||||
_ ->
|
||||
node_flat:publish_item(NodeId, Publisher, Model,
|
||||
node_flat:publish_item(NodeIdx, JID, PublishModel,
|
||||
MaxItems, ItemId, Payload)
|
||||
end;
|
||||
Err ->
|
||||
Err
|
||||
Error ->
|
||||
Error
|
||||
end.
|
||||
|
||||
|
||||
-spec(find_opt/2 ::
|
||||
(
|
||||
Key :: atom(),
|
||||
Options :: [] | [Option::nodeOption()])
|
||||
-> Value :: 'false' | term()
|
||||
).
|
||||
|
||||
find_opt(_, []) -> false;
|
||||
find_opt(Option, [{Option, Value} | _]) -> Value;
|
||||
find_opt(Option, [_ | T]) -> find_opt(Option, T).
|
||||
find_opt(Key, [{Key, Value} | _]) -> Value;
|
||||
find_opt(Key, [_ | Options]) -> find_opt(Key, Options).
|
||||
|
||||
remove_extra_items(NodeId, MaxItems, ItemIds) ->
|
||||
node_flat:remove_extra_items(NodeId, MaxItems, ItemIds).
|
||||
|
||||
delete_item(NodeId, Publisher, PublishModel, ItemId) ->
|
||||
node_flat:delete_item(NodeId, Publisher, PublishModel, ItemId).
|
||||
-spec(remove_extra_items/3 ::
|
||||
(
|
||||
NodeIdx :: nodeIdx(),
|
||||
MaxItems :: 'unlimited' | integer(),
|
||||
ItemsIds :: [ItemId::itemId()])
|
||||
-> {'result',
|
||||
{OldItems :: [] | [ItemId::itemId()],
|
||||
NewItems :: [] | [ItemId::itemId()]}}
|
||||
).
|
||||
|
||||
purge_node(NodeId, Owner) ->
|
||||
node_flat:purge_node(NodeId, Owner).
|
||||
remove_extra_items(NodeIdx, MaxItems, ItemIds) ->
|
||||
node_flat:remove_extra_items(NodeIdx, MaxItems, ItemIds).
|
||||
|
||||
get_entity_affiliations(Host, Owner) ->
|
||||
node_flat:get_entity_affiliations(Host, Owner).
|
||||
|
||||
get_node_affiliations(NodeId) ->
|
||||
node_flat:get_node_affiliations(NodeId).
|
||||
-spec(delete_item/4 ::
|
||||
(
|
||||
NodeIdx :: nodeIdx(),
|
||||
JID :: jidEntity(),
|
||||
PublishModel :: atom(),
|
||||
ItemId :: itemId())
|
||||
-> {'result', {'default', 'broadcast'}} | {'error', _}
|
||||
).
|
||||
|
||||
get_affiliation(NodeId, Owner) ->
|
||||
node_flat:get_affiliation(NodeId, Owner).
|
||||
delete_item(NodeIdx, JID, PublishModel, ItemId) ->
|
||||
node_flat:delete_item(NodeIdx, JID, PublishModel, ItemId).
|
||||
|
||||
set_affiliation(NodeId, Owner, Affiliation) ->
|
||||
node_flat:set_affiliation(NodeId, Owner, Affiliation).
|
||||
|
||||
get_entity_subscriptions(Host, Owner) ->
|
||||
node_flat:get_entity_subscriptions(Host, Owner).
|
||||
-spec(purge_node/2 ::
|
||||
(
|
||||
NodeIdx :: nodeIdx(),
|
||||
JID :: jidEntity())
|
||||
-> {'result', {'default', 'broadcast'}} | {'error', 'forbidden'}
|
||||
).
|
||||
|
||||
get_node_subscriptions(NodeId) ->
|
||||
node_flat:get_node_subscriptions(NodeId).
|
||||
purge_node(NodeIdx, JID) ->
|
||||
node_flat:purge_node(NodeIdx, JID).
|
||||
|
||||
get_subscriptions(NodeId, Owner) ->
|
||||
node_flat:get_subscriptions(NodeId, Owner).
|
||||
|
||||
set_subscriptions(NodeId, Owner, Subscription, SubId) ->
|
||||
node_flat:set_subscriptions(NodeId, Owner, Subscription, SubId).
|
||||
-spec(get_entity_affiliations/2 ::
|
||||
(
|
||||
Host :: binary(),
|
||||
JID :: jidEntity())
|
||||
-> {'result', Reply :: [] | [{Node::pubsubNode(), Affiliation::affiliation()}]}
|
||||
).
|
||||
|
||||
get_pending_nodes(Host, Owner) ->
|
||||
node_flat:get_pending_nodes(Host, Owner).
|
||||
get_entity_affiliations(Host, JID) ->
|
||||
node_flat:get_entity_affiliations(Host, JID).
|
||||
|
||||
get_states(NodeId) ->
|
||||
node_flat:get_states(NodeId).
|
||||
|
||||
get_state(NodeId, JID) ->
|
||||
node_flat:get_state(NodeId, JID).
|
||||
-spec(get_node_affiliations/1 ::
|
||||
(
|
||||
NodeIdx :: nodeIdx())
|
||||
-> {'result', [] | [{Entity::fullUsr(), Affiliation::affiliation()}]}
|
||||
).
|
||||
|
||||
get_node_affiliations(NodeIdx) ->
|
||||
node_flat:get_node_affiliations(NodeIdx).
|
||||
|
||||
|
||||
-spec(get_affiliation/2 ::
|
||||
(
|
||||
NodeIdx :: nodeIdx(),
|
||||
JID :: jidEntity())
|
||||
-> {'result', Affiliation::affiliation()}
|
||||
).
|
||||
|
||||
get_affiliation(NodeIdx, JID) ->
|
||||
node_flat:get_affiliation(NodeIdx, JID).
|
||||
|
||||
|
||||
-spec(set_affiliation/3 ::
|
||||
(
|
||||
NodeIdx :: nodeIdx(),
|
||||
JID :: jidEntity(),
|
||||
Affiliation :: affiliation())
|
||||
-> 'ok' | {error, 'internal-server-error'}
|
||||
).
|
||||
|
||||
set_affiliation(NodeIdx, JID, Affiliation) ->
|
||||
node_flat:set_affiliation(NodeIdx, JID, Affiliation).
|
||||
|
||||
|
||||
-spec(get_entity_subscriptions/2 ::
|
||||
(
|
||||
Host :: hostPubsub(),
|
||||
JID :: jidEntity())
|
||||
-> {'result', []
|
||||
| [{Node :: pubsubNode(),
|
||||
Subscription :: subscription(),
|
||||
SubId :: subId(),
|
||||
Entity :: fullUsr()}]}
|
||||
).
|
||||
|
||||
get_entity_subscriptions(Host, JID) ->
|
||||
node_flat:get_entity_subscriptions(Host, JID).
|
||||
|
||||
|
||||
-spec(get_node_subscriptions/1 ::
|
||||
(
|
||||
NodeIdx :: nodeIdx())
|
||||
-> {'result', []
|
||||
| [{Entity::fullUsr(), 'none'}]
|
||||
| [{Entity::fullUsr(), Subscription::subscription(), SubId::subId()}]}
|
||||
).
|
||||
|
||||
get_node_subscriptions(NodeIdx) ->
|
||||
node_flat:get_node_subscriptions(NodeIdx).
|
||||
|
||||
|
||||
-spec(get_subscriptions/2 ::
|
||||
(
|
||||
NodeIdx :: nodeIdx(),
|
||||
JID :: jidEntity())
|
||||
-> {'result', Subscriptions :: [] | [{Subscription::subscription(), SubId::subId()}]}
|
||||
).
|
||||
|
||||
get_subscriptions(NodeIdx, JID) ->
|
||||
node_flat:get_subscriptions(NodeIdx, JID).
|
||||
|
||||
|
||||
-spec(set_subscriptions/4 ::
|
||||
(
|
||||
NodeIdx :: nodeIdx(),
|
||||
JID :: jidEntity(),
|
||||
Subscription :: subscription(),
|
||||
SubId :: subId())
|
||||
-> 'ok'
|
||||
| {Subscription::subscription(), SubId::subId()}
|
||||
| {error, _}
|
||||
).
|
||||
|
||||
set_subscriptions(NodeIdx, JID, Subscription, SubId) ->
|
||||
node_flat:set_subscriptions(NodeIdx, JID, Subscription, SubId).
|
||||
|
||||
|
||||
-spec(get_pending_nodes/2 ::
|
||||
(
|
||||
Host :: hostPubsub(),
|
||||
JID :: jidEntity())
|
||||
-> 'false' | {'value', NodeId::nodeId()}
|
||||
).
|
||||
|
||||
get_pending_nodes(Host, JID) ->
|
||||
node_flat:get_pending_nodes(Host, JID).
|
||||
|
||||
|
||||
-spec(get_states/1 ::
|
||||
(
|
||||
NodeIdx :: nodeIdx())
|
||||
-> {'result', States :: [] | [State::pubsubState()]}
|
||||
).
|
||||
|
||||
get_states(NodeIdx) ->
|
||||
node_flat:get_states(NodeIdx).
|
||||
|
||||
|
||||
-spec(get_state/2 ::
|
||||
(
|
||||
NodeIdx :: nodeIdx(),
|
||||
Entity :: fullUsr())
|
||||
-> State::pubsubState()
|
||||
).
|
||||
|
||||
get_state(NodeIdx, Entity) ->
|
||||
node_flat:get_state(NodeIdx, Entity).
|
||||
|
||||
|
||||
-spec(set_state/1 ::
|
||||
(
|
||||
State :: pubsubState())
|
||||
-> 'ok' | {error, 'internal-server-error'}
|
||||
).
|
||||
|
||||
set_state(State) ->
|
||||
node_flat:set_state(State).
|
||||
|
||||
get_items(NodeId, From) ->
|
||||
node_flat:get_items(NodeId, From).
|
||||
|
||||
get_items(NodeId, JID, AccessModel, PresenceSubscription,
|
||||
-spec(get_items/2 ::
|
||||
(
|
||||
NodeIdx :: nodeIdx(),
|
||||
Entity :: fullUsr())
|
||||
-> {'result', Items :: [] | [Item::pubsubItem()]}
|
||||
).
|
||||
|
||||
get_items(NodeIdx, Entity) ->
|
||||
node_flat:get_items(NodeIdx, Entity).
|
||||
|
||||
|
||||
-spec(get_items/6 ::
|
||||
(
|
||||
NodeIdx :: nodeIdx(),
|
||||
JID :: jidEntity(),
|
||||
AccessModel :: accessModel(),
|
||||
PresenceSubscription :: boolean(),
|
||||
RosterGroup :: boolean(),
|
||||
SubId :: subId())
|
||||
-> {'result', Items :: [] | [Item::pubsubItem()]}
|
||||
| {'error', _}
|
||||
).
|
||||
|
||||
get_items(NodeIdx, JID, AccessModel, PresenceSubscription,
|
||||
RosterGroup, SubId) ->
|
||||
node_flat:get_items(NodeId, JID, AccessModel, PresenceSubscription,
|
||||
node_flat:get_items(NodeIdx, JID, AccessModel, PresenceSubscription,
|
||||
RosterGroup, SubId).
|
||||
|
||||
get_item(NodeId, ItemId) ->
|
||||
node_flat:get_item(NodeId, ItemId).
|
||||
|
||||
get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription,
|
||||
-spec(get_item/2 ::
|
||||
(
|
||||
NodeIdx :: nodeIdx(),
|
||||
ItemId :: itemId())
|
||||
-> {'result', Item::pubsubItem()} | {'error', 'item-not-found'}
|
||||
).
|
||||
|
||||
get_item(NodeIdx, ItemId) ->
|
||||
node_flat:get_item(NodeIdx, ItemId).
|
||||
|
||||
|
||||
-spec(get_item/7 ::
|
||||
(
|
||||
NodeIdx :: nodeIdx(),
|
||||
ItemId :: itemId(),
|
||||
JID :: jidEntity(),
|
||||
AccessModel :: accessModel(),
|
||||
PresenceSubscription :: boolean(),
|
||||
RosterGroup :: boolean(),
|
||||
SubId :: subId())
|
||||
-> {'result', Item::pubsubItem()} | {'error', 'item-not-found'}
|
||||
).
|
||||
|
||||
get_item(NodeIdx, ItemId, JID, AccessModel, PresenceSubscription,
|
||||
RosterGroup, SubId) ->
|
||||
node_flat:get_item(NodeId, ItemId, JID, AccessModel,
|
||||
node_flat:get_item(NodeIdx, ItemId, JID, AccessModel,
|
||||
PresenceSubscription, RosterGroup, SubId).
|
||||
|
||||
|
||||
-spec(set_item/1 ::
|
||||
(
|
||||
Item :: pubsubItem())
|
||||
-> 'ok' | {error, 'internal-server-error'}
|
||||
).
|
||||
|
||||
set_item(Item) ->
|
||||
node_flat:set_item(Item).
|
||||
|
||||
|
@ -51,128 +51,265 @@
|
||||
%%====================================================================
|
||||
%% API
|
||||
%%====================================================================
|
||||
-spec(init/3 ::
|
||||
(
|
||||
Host :: string(),
|
||||
ServerHost :: string(),
|
||||
Opts :: [{Key::atom(), Value::term()}])
|
||||
-> 'ok'
|
||||
).
|
||||
|
||||
init(Host, ServerHost, Opts) ->
|
||||
nodetree_tree:init(Host, ServerHost, Opts).
|
||||
|
||||
|
||||
-spec(terminate/2 ::
|
||||
(
|
||||
Host :: string(),
|
||||
ServerHost :: string())
|
||||
-> 'ok'
|
||||
).
|
||||
|
||||
terminate(Host, ServerHost) ->
|
||||
nodetree_tree:terminate(Host, ServerHost).
|
||||
|
||||
create_node(Key, Node, Type, Owner, Options, Parents) ->
|
||||
OwnerJID = jlib:short_prepd_bare_jid(Owner),
|
||||
case find_node(Key, Node) of
|
||||
|
||||
-spec(create_node/6 ::
|
||||
(
|
||||
Host :: hostPubsub(),
|
||||
NodeId :: nodeId(),
|
||||
Type :: nodeType(),
|
||||
JID :: jidEntity(),
|
||||
Options :: [nodeOption()],
|
||||
ParentNodeIds :: [] | [nodeId()])
|
||||
-> {'ok', NodeIdx::nodeIdx()} | {'error', _}
|
||||
).
|
||||
|
||||
create_node(Host, NodeId, Type, #jid{node = U, domain = S} = _JID, Options, ParentNodeIds) ->
|
||||
case find_node(Host, NodeId) of
|
||||
false ->
|
||||
Nidx = pubsub_index:new(node),
|
||||
N = #pubsub_node{id = oid(Key, Node),
|
||||
idx = Nidx,
|
||||
NodeIdx = pubsub_index:new(node),
|
||||
Node = #pubsub_node{id = {Host, NodeId},
|
||||
idx = NodeIdx,
|
||||
type = Type,
|
||||
parents = Parents,
|
||||
owners = [OwnerJID],
|
||||
parents = ParentNodeIds,
|
||||
owners = [_Owner = {U,S,undefined}],
|
||||
options = Options},
|
||||
case set_node(N) of
|
||||
ok -> {ok, Nidx};
|
||||
case set_node(Node) of
|
||||
ok -> {ok, NodeIdx};
|
||||
Other -> Other
|
||||
end;
|
||||
_ ->
|
||||
{error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'conflict')}
|
||||
end.
|
||||
|
||||
set_node(#pubsub_node{id = {Key, _},
|
||||
|
||||
-spec(set_node/1 ::
|
||||
(
|
||||
Node :: pubsubNode())
|
||||
-> 'ok' | {'error', _}
|
||||
).
|
||||
|
||||
set_node(#pubsub_node{id = {Host, _},
|
||||
owners = Owners,
|
||||
options = Options} = Node) ->
|
||||
Parents = find_opt(collection, ?DEFAULT_PARENTS, Options),
|
||||
case validate_parentage(Key, Owners, Parents) of
|
||||
ParentNodeIds = find_opt('collection', ?DEFAULT_PARENTS, Options),
|
||||
case validate_parentage(Host, Owners, ParentNodeIds) of
|
||||
true ->
|
||||
%% Update parents whenever the config changes.
|
||||
mnesia:write(Node#pubsub_node{parents = Parents});
|
||||
mnesia:write(Node#pubsub_node{parents = ParentNodeIds});
|
||||
Other ->
|
||||
Other
|
||||
end.
|
||||
|
||||
delete_node(Key, Node) ->
|
||||
case find_node(Key, Node) of
|
||||
|
||||
-spec(delete_node/2 ::
|
||||
(
|
||||
Host :: hostPubsub(),
|
||||
NodeId :: nodeId())
|
||||
-> [pubsubNode()] | {'error', _}
|
||||
).
|
||||
|
||||
delete_node(Host, NodeId) ->
|
||||
case find_node(Host, NodeId) of
|
||||
false ->
|
||||
{error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'item-not-found')};
|
||||
Record ->
|
||||
ParentNode ->
|
||||
%% Find all of N's children, update their configs to
|
||||
%% remove N from the collection setting.
|
||||
lists:foreach(fun (#pubsub_node{options = Opts} = Child) ->
|
||||
NewOpts = remove_config_parent(Node, Opts),
|
||||
Parents = find_opt(collection, ?DEFAULT_PARENTS, NewOpts),
|
||||
lists:foreach(fun (#pubsub_node{options = Options} = Node) ->
|
||||
NewOptions = remove_config_parent(NodeId, Options),
|
||||
Parents = find_opt('collection', ?DEFAULT_PARENTS, NewOptions),
|
||||
ok = mnesia:write(pubsub_node,
|
||||
Child#pubsub_node{
|
||||
Node#pubsub_node{
|
||||
parents = Parents,
|
||||
options = NewOpts},
|
||||
options = NewOptions},
|
||||
write)
|
||||
end, get_subnodes(Key, Node)),
|
||||
end, get_subnodes(Host, NodeId)),
|
||||
|
||||
%% Remove and return the requested node.
|
||||
pubsub_index:free(node, Record#pubsub_node.idx),
|
||||
mnesia:delete_object(pubsub_node, Record, write),
|
||||
[Record]
|
||||
pubsub_index:free(node, ParentNode#pubsub_node.idx),
|
||||
mnesia:delete_object(pubsub_node, ParentNode, write),
|
||||
[ParentNode]
|
||||
end.
|
||||
|
||||
options() ->
|
||||
nodetree_tree:options().
|
||||
|
||||
get_node(Host, Node, _From) ->
|
||||
get_node(Host, Node).
|
||||
-spec(options/0 :: () -> Options::[Option::nodeOption()]).
|
||||
%Options::[{'virtual_tree', 'false'}])
|
||||
|
||||
get_node(Host, Node) ->
|
||||
case find_node(Host, Node) of
|
||||
options() -> nodetree_tree:options().
|
||||
|
||||
|
||||
-spec(get_node/3 ::
|
||||
(
|
||||
Host :: hostPubsub(),
|
||||
NodeId :: nodeId(),
|
||||
JID :: jidEntity())
|
||||
-> pubsubNode() | {'error', _}
|
||||
).
|
||||
|
||||
get_node(Host, NodeId, _JID) ->
|
||||
get_node(Host, NodeId).
|
||||
|
||||
|
||||
-spec(get_node/2 ::
|
||||
(
|
||||
Host :: hostPubsub(),
|
||||
NodeId :: nodeId())
|
||||
-> pubsubNode() | {'error', _}
|
||||
).
|
||||
|
||||
get_node(Host, NodeId) ->
|
||||
case find_node(Host, NodeId) of
|
||||
false -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'item-not-found')};
|
||||
Record -> Record
|
||||
Node -> Node
|
||||
end.
|
||||
|
||||
get_node(Node) ->
|
||||
nodetree_tree:get_node(Node).
|
||||
|
||||
get_nodes(Key, From) ->
|
||||
nodetree_tree:get_nodes(Key, From).
|
||||
-spec(get_node/1 ::
|
||||
(
|
||||
NodeIdx :: nodeIdx())
|
||||
-> pubsubNode() | {'error', 'item-not-found'}
|
||||
).
|
||||
|
||||
get_nodes(Key) ->
|
||||
nodetree_tree:get_nodes(Key).
|
||||
get_node(NodeIdx) ->
|
||||
nodetree_tree:get_node(NodeIdx).
|
||||
|
||||
get_parentnodes(Host, Node, _From) ->
|
||||
case find_node(Host, Node) of
|
||||
|
||||
-spec(get_nodes/2 ::
|
||||
(
|
||||
Host :: hostPubsub(),
|
||||
JID :: jidEntity())
|
||||
-> Nodes :: [] | [Node::pubsubNode()]
|
||||
).
|
||||
|
||||
get_nodes(Host, JID) ->
|
||||
nodetree_tree:get_nodes(Host, JID).
|
||||
|
||||
|
||||
-spec(get_nodes/1 ::
|
||||
(
|
||||
Host :: hostPubsub())
|
||||
-> Nodes :: [] | [Node::pubsubNode()]
|
||||
).
|
||||
|
||||
get_nodes(Host) ->
|
||||
nodetree_tree:get_nodes(Host).
|
||||
|
||||
|
||||
-spec(get_parentnodes/3 ::
|
||||
(
|
||||
Host :: hostPubsub(),
|
||||
NodeId :: nodeId(),
|
||||
JID :: jidEntity())
|
||||
-> ParentNodes :: [] | [ParentNode::pubsubNode()]
|
||||
).
|
||||
|
||||
get_parentnodes(Host, NodeId, _JID) ->
|
||||
case find_node(Host, NodeId) of
|
||||
false -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'item-not-found')};
|
||||
#pubsub_node{parents = Parents} ->
|
||||
Q = qlc:q([N || #pubsub_node{id = {NHost, NNode}} = N <- mnesia:table(pubsub_node),
|
||||
Parent <- Parents,
|
||||
#pubsub_node{parents = ParentNodeIds} ->
|
||||
Q = qlc:q([Node || #pubsub_node{id = {NHost, NNodeId}} = Node
|
||||
<- mnesia:table(pubsub_node),
|
||||
ParentNodeId <- ParentNodeIds,
|
||||
Host == NHost,
|
||||
Parent == NNode]),
|
||||
ParentNodeId == NNodeId]),
|
||||
qlc:e(Q)
|
||||
end.
|
||||
|
||||
get_parentnodes_tree(Host, Node, _From) ->
|
||||
|
||||
-spec(get_parentnodes_tree/3 ::
|
||||
(
|
||||
Host :: hostPubsub(),
|
||||
NodeId :: nodeId(),
|
||||
JID :: jidEntity())
|
||||
-> [] | [{Depth::integer(), Nodes :: [] | [Node::pubsubNode()]}]
|
||||
).
|
||||
|
||||
get_parentnodes_tree(Host, NodeId, _JID) ->
|
||||
Pred = fun (Name, #pubsub_node{id = {_, NodeName}}) -> Name == NodeName end,
|
||||
Tr = fun (#pubsub_node{parents = Parents}) -> Parents end,
|
||||
traversal_helper(Pred, Tr, Host, [Node]).
|
||||
traversal_helper(Pred, Tr, Host, [NodeId]).
|
||||
|
||||
get_subnodes(Host, Node, _From) ->
|
||||
|
||||
-spec(get_subnodes/3 ::
|
||||
(
|
||||
ParentNodeHost :: hostPubsub(),
|
||||
ParentNodeId :: nodeId(),
|
||||
JID :: jidEntity())
|
||||
-> [] | [Node::pubsubNode()] | {'error', _}
|
||||
).
|
||||
|
||||
get_subnodes(Host, Node, _JID) ->
|
||||
get_subnodes(Host, Node).
|
||||
|
||||
get_subnodes(Host, <<>>) ->
|
||||
get_subnodes_helper(Host, <<>>);
|
||||
get_subnodes(Host, Node) ->
|
||||
case find_node(Host, Node) of
|
||||
|
||||
-spec(get_subnodes/2 ::
|
||||
(
|
||||
ParentNodeHost :: hostPubsub(),
|
||||
ParentNodeId :: nodeId())
|
||||
-> [] | [Node::pubsubNode()] | {'error', _}
|
||||
).
|
||||
|
||||
get_subnodes(ParentNodeHost, <<>>) ->
|
||||
get_subnodes_helper(ParentNodeHost, <<>>);
|
||||
get_subnodes(ParentNodeHost, ParentNodeId) ->
|
||||
case find_node(ParentNodeHost, ParentNodeId) of
|
||||
false -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'item-not-found')};
|
||||
_ -> get_subnodes_helper(Host, Node)
|
||||
_ -> get_subnodes_helper(ParentNodeHost, ParentNodeId)
|
||||
end.
|
||||
|
||||
get_subnodes_helper(Host, Node) ->
|
||||
Q = qlc:q([Record || #pubsub_node{id = {NHost, _},
|
||||
parents = Parents} = Record <- mnesia:table(pubsub_node),
|
||||
Host == NHost,
|
||||
lists:member(Node, Parents)]),
|
||||
|
||||
-spec(get_subnodes_helper/2 ::
|
||||
(
|
||||
ParentNodeHost :: hostPubsub(),
|
||||
ParentNodeId :: nodeId())
|
||||
-> SubNodes :: [] | [Node::pubsubNode()]
|
||||
).
|
||||
|
||||
get_subnodes_helper(ParentNodeHost, ParentNodeId) ->
|
||||
Q = qlc:q([Node || #pubsub_node{id = {Host, _},
|
||||
parents = ParentNodeIds} = Node <- mnesia:table(pubsub_node),
|
||||
ParentNodeHost == Host,
|
||||
lists:member(ParentNodeId, ParentNodeIds)]),
|
||||
qlc:e(Q).
|
||||
|
||||
get_subnodes_tree(Host, Node, From) ->
|
||||
Pred = fun (N, #pubsub_node{parents = Parents}) ->
|
||||
lists:member(N, Parents)
|
||||
|
||||
-spec(get_subnodes_tree/3 ::
|
||||
(
|
||||
ParentNodeHost :: hostPubsub(),
|
||||
ParentNodeId :: nodeId(),
|
||||
JID :: jidEntity())
|
||||
-> [] | [{Depth::integer(), Nodes :: [] | [Node::pubsubNode()]}]
|
||||
).
|
||||
|
||||
get_subnodes_tree(Host, ParentNodeId, JID) ->
|
||||
Pred = fun(NodeId, #pubsub_node{parents = ParentNodeIds}) ->
|
||||
lists:member(NodeId, ParentNodeIds)
|
||||
end,
|
||||
Tr = fun (#pubsub_node{id = {_, N}}) -> [N] end,
|
||||
traversal_helper(Pred, Tr, 1, Host, [Node],
|
||||
[{0, [get_node(Host, Node, From)]}]).
|
||||
Tr = fun (#pubsub_node{id = {_, NodeId}}) -> [NodeId] end,
|
||||
traversal_helper(Pred, Tr, 1, Host, [ParentNodeId],
|
||||
[{0, [get_node(Host, ParentNodeId, JID)]}]).
|
||||
|
||||
%%====================================================================
|
||||
%% Internal functions
|
||||
@ -181,8 +318,15 @@ oid(Key, Name) -> {Key, Name}.
|
||||
|
||||
%% Key = jlib:jid() | host()
|
||||
%% Node = string()
|
||||
find_node(Key, Node) ->
|
||||
case mnesia:read(pubsub_node, oid(Key, Node), read) of
|
||||
-spec(find_node/2 ::
|
||||
(
|
||||
Host :: hostPubsub(),
|
||||
NodeId :: nodeId())
|
||||
-> pubsubNode() | 'false'
|
||||
).
|
||||
|
||||
find_node(Host, NodeId) ->
|
||||
case mnesia:read({pubsub_node, {Host, NodeId}}) of
|
||||
[] -> false;
|
||||
[Node] -> Node
|
||||
end.
|
||||
@ -190,53 +334,109 @@ find_node(Key, Node) ->
|
||||
%% Key = jlib:jid() | host()
|
||||
%% Default = term()
|
||||
%% Options = [{Key = atom(), Value = term()}]
|
||||
-spec(find_opt/3 ::
|
||||
(
|
||||
Key :: atom(),
|
||||
Default :: term(),
|
||||
Options :: [Option::nodeOption()])
|
||||
-> Value::term()
|
||||
).
|
||||
|
||||
find_opt(Key, Default, Options) ->
|
||||
case lists:keysearch(Key, 1, Options) of
|
||||
{value, {Key, Val}} -> Val;
|
||||
{value, {Key, Value}} -> Value;
|
||||
_ -> Default
|
||||
end.
|
||||
|
||||
traversal_helper(Pred, Tr, Host, Nodes) ->
|
||||
traversal_helper(Pred, Tr, 0, Host, Nodes, []).
|
||||
|
||||
-spec(traversal_helper/4 ::
|
||||
(
|
||||
Pred :: fun(),
|
||||
Tr :: fun(),
|
||||
ParentNodeHost :: hostPubsub(),
|
||||
ParentNodeIds :: [] | [ParentNodeId::nodeId()])
|
||||
-> [] | [{Depth::integer(), Nodes :: [] | [Node::pubsubNode()]}]
|
||||
).
|
||||
|
||||
traversal_helper(Pred, Tr, ParentNodeHost, ParentNodeIds) ->
|
||||
traversal_helper(Pred, Tr, 0, ParentNodeHost, ParentNodeIds, []).
|
||||
|
||||
|
||||
-spec(traversal_helper/6 ::
|
||||
(
|
||||
Pred :: fun(),
|
||||
Tr :: fun(),
|
||||
Depth :: integer(),
|
||||
ParentNodeHost :: hostPubsub(),
|
||||
ParentNodeIds :: [] | [ParentNodeId::nodeId()],
|
||||
Acc :: [] | [{Depth::integer(), Nodes :: [] | [Node::pubsubNode()]}])
|
||||
-> [] | [{Depth::integer(), Nodes :: [] | [Node::pubsubNode()]}]
|
||||
).
|
||||
|
||||
traversal_helper(_Pred, _Tr, _Depth, _Host, [], Acc) ->
|
||||
Acc;
|
||||
traversal_helper(Pred, Tr, Depth, Host, Nodes, Acc) ->
|
||||
Q = qlc:q([Record || #pubsub_node{id = {NHost, _}} = Record <- mnesia:table(pubsub_node),
|
||||
Node <- Nodes,
|
||||
Host == NHost,
|
||||
Pred(Node, Node)]),
|
||||
traversal_helper(Pred, Tr, Depth, ParentNodeHost, ParentNodeIds, Acc) ->
|
||||
Q = qlc:q([Node || #pubsub_node{id = {Host, _}} = Node <- mnesia:table(pubsub_node),
|
||||
ParentNodeId <- ParentNodeIds,
|
||||
ParentNodeHost == Host,
|
||||
Pred(ParentNodeId, Node)]),
|
||||
Nodes = qlc:e(Q),
|
||||
Names = lists:flatmap(Tr, Nodes),
|
||||
traversal_helper(Pred, Tr, Depth + 1, Host, Names, [{Depth, Nodes} | Acc]).
|
||||
Ids = lists:flatmap(Tr, Nodes),
|
||||
traversal_helper(Pred, Tr, Depth + 1, ParentNodeHost, Ids, [{Depth, Nodes} | Acc]).
|
||||
|
||||
remove_config_parent(Node, Options) ->
|
||||
remove_config_parent(Node, Options, []).
|
||||
|
||||
remove_config_parent(_Node, [], Acc) ->
|
||||
-spec(remove_config_parent/2 ::
|
||||
(
|
||||
NodeId :: nodeId(),
|
||||
Options :: [Option::nodeOption()])
|
||||
-> [Option::nodeOption()]
|
||||
).
|
||||
|
||||
remove_config_parent(NodeId, Options) ->
|
||||
remove_config_parent(NodeId, Options, []).
|
||||
|
||||
|
||||
-spec(remove_config_parent/3 ::
|
||||
(
|
||||
NodeId :: nodeId(),
|
||||
Options :: [] | [Option::nodeOption()],
|
||||
Acc :: [Option::nodeOption()])
|
||||
-> [Option::nodeOption()]
|
||||
).
|
||||
|
||||
remove_config_parent(_NodeId, [], Acc) ->
|
||||
lists:reverse(Acc);
|
||||
remove_config_parent(Node, [{collection, Parents} | T], Acc) ->
|
||||
remove_config_parent(Node, T,
|
||||
[{collection, lists:delete(Node, Parents)} | Acc]);
|
||||
remove_config_parent(Node, [H | T], Acc) ->
|
||||
remove_config_parent(Node, T, [H | Acc]).
|
||||
remove_config_parent(NodeId, [{'collection', ParentNodeIds} | Options], Acc) ->
|
||||
remove_config_parent(NodeId, Options,
|
||||
[{'collection', lists:delete(NodeId, ParentNodeIds)} | Acc]);
|
||||
remove_config_parent(NodeId, [Option | Options], Acc) ->
|
||||
remove_config_parent(NodeId, Options, [Option | Acc]).
|
||||
|
||||
validate_parentage(_Key, _Owners, []) ->
|
||||
|
||||
-spec(validate_parentage/3 ::
|
||||
(
|
||||
Host :: hostPubsub(),
|
||||
Owners :: [Owner::bareUsr()],
|
||||
ParentNodeIds :: [] | [ParentNodeId::nodeId()] | [ParentNodeId :: nodeId() | []])
|
||||
-> 'true' | {'error', _}
|
||||
).
|
||||
|
||||
validate_parentage(_Host, _Owners, []) ->
|
||||
true;
|
||||
validate_parentage(Key, Owners, [[] | T]) ->
|
||||
validate_parentage(Key, Owners, T);
|
||||
validate_parentage(Key, Owners, [<<>> | T]) ->
|
||||
validate_parentage(Key, Owners, T);
|
||||
validate_parentage(Key, Owners, [ParentId | T]) ->
|
||||
case find_node(Key, ParentId) of
|
||||
validate_parentage(Host, Owners, [[] | ParentNodeIds]) ->
|
||||
validate_parentage(Host, Owners, ParentNodeIds);
|
||||
validate_parentage(Host, Owners, [<<>> | ParentNodeIds]) ->
|
||||
validate_parentage(Host, Owners, ParentNodeIds);
|
||||
validate_parentage(Host, Owners, [ParentNodeId | ParentNodeIds]) ->
|
||||
case find_node(Host, ParentNodeId) of
|
||||
false -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'item_not_found')};
|
||||
#pubsub_node{owners = POwners, options = POptions} ->
|
||||
NodeType = find_opt(node_type, ?DEFAULT_NODETYPE, POptions),
|
||||
MutualOwners = [O || O <- Owners, PO <- POwners,
|
||||
O == PO],
|
||||
#pubsub_node{owners = ParentNodeOwners, options = Options} ->
|
||||
NodeType = find_opt('node_type', ?DEFAULT_NODETYPE, Options),
|
||||
MutualOwners = [Owner || Owner <- Owners, ParentNodeOwner <- ParentNodeOwners,
|
||||
Owner == ParentNodeOwner],
|
||||
case {MutualOwners, NodeType} of
|
||||
{[], _} -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'forbidden')};
|
||||
{_, collection} -> validate_parentage(Key, Owners, T);
|
||||
{_, 'collection'} -> validate_parentage(Host, Owners, ParentNodeIds);
|
||||
{_, _} -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'not-allowed')}
|
||||
end
|
||||
end.
|
||||
@ -244,6 +444,12 @@ validate_parentage(Key, Owners, [ParentId | T]) ->
|
||||
%% @spec (Host) -> jid()
|
||||
%% Host = host()
|
||||
%% @doc <p>Generate pubsub service JID.</p>
|
||||
-spec(service_jid/1 ::
|
||||
(
|
||||
Host :: hostPubsub())
|
||||
-> ServiceJID :: jidContact() | jidComponent() %% should only return jidContact()
|
||||
).
|
||||
|
||||
service_jid(Host) ->
|
||||
case Host of
|
||||
{U,S,_} -> exmpp_jid:make(U, S);
|
||||
|
@ -157,7 +157,7 @@ get_node(Host, NodeId) ->
|
||||
-spec(get_node/1 ::
|
||||
(
|
||||
NodeIdx :: nodeIdx())
|
||||
-> pubsubNode() | {error, 'item-not-found'} | any()
|
||||
-> pubsubNode() | {'error', 'item-not-found'}
|
||||
).
|
||||
|
||||
get_node(NodeIdx) ->
|
||||
|
Loading…
Reference in New Issue
Block a user