./ct_report/coverage/node_pep.COVER.html

1 %%% ====================================================================
2 %%% ``The contents of this file are subject to the Erlang Public License,
3 %%% Version 1.1, (the "License"); you may not use this file except in
4 %%% compliance with the License. You should have received a copy of the
5 %%% Erlang Public License along with this software. If not, it can be
6 %%% retrieved via the world wide web at http://www.erlang.org/.
7 %%%
8 %%%
9 %%% Software distributed under the License is distributed on an "AS IS"
10 %%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
11 %%% the License for the specific language governing rights and limitations
12 %%% under the License.
13 %%%
14 %%%
15 %%% The Initial Developer of the Original Code is ProcessOne.
16 %%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne
17 %%% All Rights Reserved.''
18 %%% This software is copyright 2006-2015, ProcessOne.
19 %%%
20 %%% @copyright 2006-2015 ProcessOne
21 %%% @author Christophe Romain <christophe.romain@process-one.net>
22 %%% [http://www.process-one.net/]
23 %%% @end
24 %%% ====================================================================
25
26 -module(node_pep).
27 -behaviour(gen_pubsub_node).
28 -author('christophe.romain@process-one.net').
29
30 -include("mongoose.hrl").
31 -include("pubsub.hrl").
32 -include("jlib.hrl").
33
34 %%% @doc The module <strong>{@module}</strong> is the pep PubSub plugin.
35 %%% <p>PubSub plugin nodes are using the {@link gen_pubsub_node} behaviour.</p>
36
37 -export([based_on/0, init/3, terminate/2, options/0, features/0,
38 create_node_permission/6, delete_node/1,
39 unsubscribe_node/4, node_to_path/1,
40 get_entity_affiliations/2, get_entity_affiliations/3,
41 get_entity_subscriptions/2, get_entity_subscriptions/4,
42 should_delete_when_owner_removed/0, check_publish_options/2
43 ]).
44
45 -ignore_xref([get_entity_affiliations/3, get_entity_subscriptions/4, check_publish_options/2]).
46
47 84 based_on() -> node_flat.
48
49 init(Host, ServerHost, Opts) ->
50 4 node_flat:init(Host, ServerHost, Opts),
51 4 complain_if_modcaps_disabled(ServerHost),
52 4 ok.
53
54 terminate(Host, ServerHost) ->
55 4 node_flat:terminate(Host, ServerHost),
56 4 ok.
57
58 options() ->
59 20 [{deliver_payloads, true},
60 {notify_config, false},
61 {notify_delete, false},
62 {notify_retract, false},
63 {purge_offline, false},
64 {persist_items, true},
65 {max_items, 1},
66 {subscribe, true},
67 {access_model, presence},
68 {roster_groups_allowed, []},
69 {publish_model, publishers},
70 {notification_type, headline},
71 {max_payload_size, ?MAX_PAYLOAD_SIZE},
72 {send_last_published_item, on_sub_and_presence},
73 {deliver_notifications, true},
74 {presence_based_delivery, true}].
75
76 features() ->
77 204 [<<"create-nodes">>,
78 <<"auto-create">>,
79 <<"auto-subscribe">>,
80 <<"delete-nodes">>,
81 <<"delete-items">>,
82 <<"filtered-notifications">>,
83 <<"modify-affiliations">>,
84 <<"outcast-affiliation">>,
85 <<"persistent-items">>,
86 <<"publish">>,
87 <<"publish-options">>,
88 <<"purge-nodes">>,
89 <<"retract-items">>,
90 <<"retrieve-affiliations">>,
91 <<"retrieve-items">>,
92 <<"retrieve-subscriptions">>,
93 <<"subscribe">>].
94
95 -spec check_publish_options(#{binary() => [binary()]} | invalid_form, #{binary() => [binary()]}) ->
96 boolean().
97 check_publish_options(invalid_form, _) ->
98 1 true;
99 check_publish_options(PublishOptions, NodeOptions) ->
100 22 F = fun(Key, Value) ->
101 20 case string:split(Key, "#") of
102 [<<"pubsub">>, Key2] ->
103 19 compare_values(Value, maps:get(Key2, NodeOptions, null));
104 1 _ -> true
105 end
106 end,
107 22 maps:size(maps:filter(F, PublishOptions)) =/= 0.
108
109 -spec compare_values([binary()], [binary()] | null) -> boolean().
110 compare_values(_, null) ->
111 1 true;
112 compare_values(Value1, Value2) ->
113 18 lists:sort(Value1) =/= lists:sort(Value2).
114
115 create_node_permission(Host, _ServerHost, _Node, _ParentNode,
116 #jid{ luser = <<>>, lserver = Host, lresource = <<>> }, _Access) ->
117
:-(
{result, true}; % pubsub service always allowed
118 create_node_permission(Host, ServerHost, _Node, _ParentNode,
119 #jid{ luser = User, lserver = Server } = Owner, Access) ->
120 20 {ok, HostType} = mongoose_domain_api:get_domain_host_type(ServerHost),
121 20 case acl:match_rule(HostType, ServerHost, Access, Owner) of
122 allow ->
123 20 case Host of
124 20 {User, Server, _} -> {result, true};
125
:-(
_ -> {result, false}
126 end;
127 _ ->
128
:-(
{result, false}
129 end.
130
131 delete_node(Nodes) ->
132 4 {result, {_, _, Result}} = node_flat:delete_node(Nodes),
133 4 {result, {[], Result}}.
134
135 unsubscribe_node(Nidx, Sender, Subscriber, SubId) ->
136
:-(
case node_flat:unsubscribe_node(Nidx, Sender, Subscriber, SubId) of
137
:-(
{error, Error} -> {error, Error};
138
:-(
{result, _} -> {result, []}
139 end.
140
141 get_entity_affiliations(Host, #jid{ lserver = D } = Owner) ->
142
:-(
get_entity_affiliations(Host, D, jid:to_lower(Owner));
143 get_entity_affiliations(Host, {_, D, _} = Owner) ->
144 55 get_entity_affiliations(Host, D, Owner).
145
146 get_entity_affiliations(Host, D, Owner) ->
147 55 {ok, States} = mod_pubsub_db_backend:get_states_by_bare(Owner),
148 55 HT = mod_pubsub:host_to_host_type(Host),
149 55 NodeTree = mod_pubsub:tree(HT),
150 55 Reply = lists:foldl(fun (#pubsub_state{stateid = {_, N}, affiliation = A}, Acc) ->
151 23 case gen_pubsub_nodetree:get_node(NodeTree, N) of
152 14 #pubsub_node{nodeid = {{_, D, _}, _}} = Node -> [{Node, A} | Acc];
153 9 _ -> Acc
154 end
155 end,
156 [], States),
157 55 {result, Reply}.
158
159 get_entity_subscriptions(Host, #jid{ lserver = D, lresource = R } = Owner) ->
160 58 get_entity_subscriptions(Host, D, R, Owner);
161 get_entity_subscriptions(Host, {_, D, R} = Owner) ->
162
:-(
get_entity_subscriptions(Host, D, R, Owner).
163
164 get_entity_subscriptions(Host, D, R, Owner) ->
165 58 LOwner = jid:to_lower(Owner),
166 58 States = case R of
167 <<>> ->
168 3 {ok, States0} = mod_pubsub_db_backend:get_states_by_lus(LOwner),
169 3 States0;
170 _ ->
171 55 {ok, States0} = mod_pubsub_db_backend:get_states_by_bare_and_full(LOwner),
172 55 States0
173 end,
174 58 HT = mod_pubsub:host_to_host_type(Host),
175 58 NodeTree = mod_pubsub:tree(HT),
176 58 Reply = lists:foldl(fun (#pubsub_state{stateid = {J, N}, subscriptions = Ss}, Acc) ->
177 1 case gen_pubsub_nodetree:get_node(NodeTree, N) of
178 #pubsub_node{nodeid = {{_, D, _}, _}} = Node ->
179 1 accumulate_entity_subscriptions(J, Node, Ss, Acc);
180 _ ->
181
:-(
Acc
182 end
183 end,
184 [], States),
185 58 {result, Reply}.
186
187 accumulate_entity_subscriptions(J, Node, Ss, Acc) ->
188 1 lists:foldl(fun({subscribed, SubId}, Acc2) ->
189
:-(
[{Node, subscribed, SubId, J} | Acc2];
190 ({pending, _SubId}, Acc2) ->
191 1 [{Node, pending, J} | Acc2];
192 (S, Acc2) ->
193
:-(
[{Node, S, J} | Acc2]
194 end, Acc, Ss).
195
196
197 node_to_path(Node) ->
198 20 node_flat:node_to_path(Node).
199
200 2 should_delete_when_owner_removed() -> true.
201
202 %%%
203 %%% Internal
204 %%%
205
206 %% @doc Check mod_caps is enabled, otherwise show warning.
207 %% The PEP plugin for mod_pubsub requires mod_caps to be enabled in the host.
208 %% Check that the mod_caps module is enabled in that Jabber Host
209 %% If not, log a warning message.
210 complain_if_modcaps_disabled(ServerHost) ->
211 4 ?WARNING_MSG_IF(
212 4 not gen_mod:is_loaded(ServerHost, mod_caps),
213 "The PEP plugin is enabled in mod_pubsub "
214 "of host ~p. This plugin requires mod_caps "
215 "to be enabled, but it isn't.",
216
:-(
[ServerHost]).
Line Hits Source